├── .eslintignore ├── .prettierignore ├── .gitattributes ├── .prettierrc.js ├── tsconfig.eslint.json ├── src ├── components │ ├── DateInput │ │ ├── index.ts │ │ └── is-date-valid │ │ │ ├── is-date-valid.ts │ │ │ └── is-date-valid.test.ts │ ├── TimeInput │ │ ├── index.ts │ │ ├── TimeInput.story.tsx │ │ ├── TimeInput.styles.ts │ │ └── TimeInput.tsx │ ├── DatePicker │ │ ├── index.ts │ │ ├── DatePicker.story.tsx │ │ └── DatePicker.tsx │ ├── YearPicker │ │ ├── index.ts │ │ ├── YearPicker.story.tsx │ │ └── YearPicker.tsx │ ├── MonthPicker │ │ ├── index.ts │ │ ├── MonthPicker.story.tsx │ │ └── MonthPicker.tsx │ ├── Day │ │ ├── index.ts │ │ ├── Day.story.tsx │ │ └── Day.styles.ts │ ├── YearLevel │ │ ├── index.ts │ │ ├── YearLevel.styles.ts │ │ └── YearLevel.story.tsx │ ├── YearsList │ │ ├── index.ts │ │ ├── YearsList.styles.ts │ │ ├── is-year-disabled │ │ │ ├── is-year-disabled.ts │ │ │ └── is-year-disabled.test.ts │ │ ├── get-years-data │ │ │ ├── get-years-data.ts │ │ │ └── get-years-data.test.ts │ │ ├── YearsList.story.tsx │ │ └── YearsList.test.tsx │ ├── MonthLevel │ │ ├── index.ts │ │ ├── MonthLevel.styles.ts │ │ └── MonthLevel.story.tsx │ ├── MonthsList │ │ ├── index.ts │ │ ├── MonthsList.styles.ts │ │ ├── is-month-disabled │ │ │ ├── is-month-disabled.ts │ │ │ └── is-month-disabled.test.ts │ │ ├── get-months-data │ │ │ ├── get-months-data.ts │ │ │ └── get-months-data.test.ts │ │ ├── MonthsList.story.tsx │ │ └── MonthsList.test.tsx │ ├── PickerControl │ │ ├── index.ts │ │ ├── PickerControl.story.tsx │ │ ├── PickerControl.styles.ts │ │ ├── PickerControl.tsx │ │ └── PickerControl.test.tsx │ ├── DateTimePicker │ │ ├── index.ts │ │ ├── DateTimePicker.styles.ts │ │ └── DateTimePicker.story.tsx │ ├── DecadeLevel │ │ ├── index.ts │ │ ├── DecadeLevel.styles.ts │ │ ├── get-decade-range │ │ │ ├── get-decade-range.ts │ │ │ └── get-decade-range.test.ts │ │ └── DecadeLevel.story.tsx │ ├── YearLevelGroup │ │ ├── index.ts │ │ ├── YearLevelGroup.styles.ts │ │ └── YearLevelGroup.story.tsx │ ├── DatePickerInput │ │ ├── index.ts │ │ └── DatePickerInput.story.tsx │ ├── HiddenDatesInput │ │ ├── index.ts │ │ ├── HiddenDatesInput.tsx │ │ └── HiddenDatesInput.test.tsx │ ├── MonthLevelGroup │ │ ├── index.ts │ │ ├── MonthLevelGroup.styles.ts │ │ └── MonthLevelGroup.story.tsx │ ├── YearPickerInput │ │ ├── index.ts │ │ ├── YearPickerInput.story.tsx │ │ └── YearPickerInput.tsx │ ├── DecadeLevelGroup │ │ ├── index.ts │ │ ├── DecadeLevelGroup.styles.ts │ │ └── DecadeLevelGroup.story.tsx │ ├── MonthPickerInput │ │ ├── index.ts │ │ ├── MonthPickerInput.story.tsx │ │ └── MonthPickerInput.tsx │ ├── Calendar │ │ ├── Calendar.styles.ts │ │ ├── index.ts │ │ ├── clamp-level │ │ │ ├── clamp-level.ts │ │ │ └── clamp-level.test.ts │ │ ├── Calendar.story.tsx │ │ └── pick-calendar-levels-props │ │ │ └── pick-calendar-levels-props.ts │ ├── CalendarHeader │ │ ├── index.ts │ │ ├── Chevron.tsx │ │ ├── CalendarHeader.story.tsx │ │ ├── CalendarHeader.styles.ts │ │ └── CalendarHeader.test.tsx │ ├── PickerInputBase │ │ ├── index.ts │ │ └── PickerInputBase.styles.ts │ ├── WeekdaysRow │ │ ├── index.ts │ │ ├── WeekdaysRow.styles.ts │ │ ├── get-weekdays-names │ │ │ ├── get-weekdays-names.ts │ │ │ └── get-weekdays-names.test.ts │ │ ├── WeekdaysRow.story.tsx │ │ ├── WeekdaysRow.test.tsx │ │ └── WeekdaysRow.tsx │ ├── DatesProvider │ │ ├── index.ts │ │ ├── use-dates-context.ts │ │ ├── DatesProvider.tsx │ │ └── use-dates-context.test.tsx │ └── Month │ │ ├── is-before-max-date │ │ ├── is-before-max-date.ts │ │ └── is-before-max-date.test.ts │ │ ├── is-after-min-date │ │ ├── is-after-min-date.ts │ │ └── is-after-min-date.test.ts │ │ ├── get-start-of-week │ │ ├── get-start-of-week.ts │ │ └── get-start-of-week.test.ts │ │ ├── index.ts │ │ ├── get-end-of-week │ │ ├── get-end-of-week.ts │ │ └── get-end-of-week.test.ts │ │ ├── Month.styles.ts │ │ ├── is-same-month │ │ ├── is-same-month.test.ts │ │ └── is-same-month.ts │ │ ├── Month.story.tsx │ │ ├── get-month-days │ │ ├── get-month-days.ts │ │ └── get-month-days.test.ts │ │ └── Month.test.tsx ├── types │ ├── index.ts │ ├── GeneralTypes.ts │ ├── DatePickerValue.ts │ ├── PickerBaseProps.ts │ └── ControlsGroupSettings.ts ├── utils │ ├── index.ts │ ├── assign-time │ │ ├── assign-time.ts │ │ └── assign-time.test.ts │ └── get-formatted-date.ts ├── hooks │ ├── index.ts │ ├── use-uncontrolled-dates │ │ └── use-uncontrolled-dates.ts │ └── use-dates-input │ │ └── use-dates-input.ts ├── tests │ ├── it-supports-get-control-ref.tsx │ ├── it-supports-get-day-ref.tsx │ ├── it-supports-on-day-click.tsx │ ├── it-supports-on-control-click.tsx │ ├── it-supports-on-control-mouse-enter.tsx │ ├── it-supports-on-control-key-down.tsx │ ├── it-supports-with-next-previous.tsx │ ├── it-supports-on-day-keydown.tsx │ ├── it-supports-clearable-props.tsx │ ├── date-input-test-helpers.ts │ ├── index.ts │ ├── it-supports-weekdays-props.tsx │ ├── it-handles-month-keyboard-events.tsx │ └── it-handles-controls-keyboard-events.tsx └── index.ts ├── .config ├── .storybook │ ├── main.js │ └── preview.tsx └── rollup.config.js ├── .editorconfig ├── jest.setup.js ├── scripts ├── nojekyll.ts ├── update-version.ts ├── docgen │ ├── generate-declarations.ts │ ├── docgen.ts │ ├── docgen-parser.ts │ └── prepare-declaration.ts ├── release.ts └── get-next-version.ts ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── jest.config.js ├── docs ├── pages │ ├── date-input.mdx │ ├── time-input.mdx │ ├── date-picker.mdx │ ├── year-picker.mdx │ ├── month-picker.mdx │ ├── date-time-picker.mdx │ ├── date-picker-input.mdx │ ├── year-picker-input.mdx │ ├── month-picker-input.mdx │ ├── index.tsx │ ├── _document.tsx │ └── _app.tsx ├── components │ ├── PageHeader │ │ ├── PageHeader.styles.ts │ │ ├── LinkItem │ │ │ ├── LinkItem.styles.ts │ │ │ └── LinkItem.tsx │ │ ├── HeaderItem │ │ │ ├── HeaderItem.styles.ts │ │ │ └── HeaderItem.tsx │ │ └── PageHeader.tsx │ ├── MdxProvider │ │ ├── MdxPrism │ │ │ └── MdxPrism.tsx │ │ ├── MdxTitle │ │ │ ├── MdxTitle.styles.ts │ │ │ └── MdxTitle.tsx │ │ ├── MdxLink │ │ │ └── MdxLink.tsx │ │ └── MdxProvider.tsx │ ├── Shell │ │ ├── Shell.tsx │ │ ├── Footer.tsx │ │ └── Header.tsx │ ├── DirectionProvider │ │ └── DirectionProvider.tsx │ └── PropsTable │ │ └── PropsTable.tsx ├── .gitignore ├── next.config.js ├── demos │ ├── index.ts │ ├── TimeInput.demo.usage.tsx │ ├── DateTimePicker.demo.usage.tsx │ └── DateInput.demo.usage.tsx ├── tsconfig.json ├── public │ └── favicon.svg ├── package.json ├── README.md └── mdx │ └── home-page.mdx ├── tsconfig.json ├── settings.ts └── LICENSE /.eslintignore: -------------------------------------------------------------------------------- 1 | .eslintrc.js -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.d.ts 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('eslint-config-mantine/.prettierrc'); 2 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["./**/*.tsx", "./**/*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /src/components/DateInput/index.ts: -------------------------------------------------------------------------------- 1 | export { DateInput } from './DateInput'; 2 | export type { DateInputProps, DateInputStylesNames } from './DateInput'; 3 | -------------------------------------------------------------------------------- /src/components/TimeInput/index.ts: -------------------------------------------------------------------------------- 1 | export { TimeInput } from './TimeInput'; 2 | export type { TimeInputProps, TimeInputStylesNames } from './TimeInput'; 3 | -------------------------------------------------------------------------------- /src/components/DatePicker/index.ts: -------------------------------------------------------------------------------- 1 | export { DatePicker } from './DatePicker'; 2 | export type { DatePickerBaseProps, DatePickerProps } from './DatePicker'; 3 | -------------------------------------------------------------------------------- /src/components/YearPicker/index.ts: -------------------------------------------------------------------------------- 1 | export { YearPicker } from './YearPicker'; 2 | export type { YearPickerProps, YearPickerBaseProps } from './YearPicker'; 3 | -------------------------------------------------------------------------------- /src/components/MonthPicker/index.ts: -------------------------------------------------------------------------------- 1 | export { MonthPicker } from './MonthPicker'; 2 | export type { MonthPickerBaseProps, MonthPickerProps } from './MonthPicker'; 3 | -------------------------------------------------------------------------------- /src/components/Day/index.ts: -------------------------------------------------------------------------------- 1 | export { Day } from './Day'; 2 | export type { DayProps, DayStylesNames } from './Day'; 3 | export type { DayStylesParams } from './Day.styles'; 4 | -------------------------------------------------------------------------------- /src/components/YearLevel/index.ts: -------------------------------------------------------------------------------- 1 | export { YearLevel } from './YearLevel'; 2 | export type { YearLevelProps, YearLevelSettings, YearLevelStylesNames } from './YearLevel'; 3 | -------------------------------------------------------------------------------- /src/components/YearsList/index.ts: -------------------------------------------------------------------------------- 1 | export { YearsList } from './YearsList'; 2 | export type { YearsListProps, YearsListSettings, YearsListStylesNames } from './YearsList'; 3 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ControlsGroupSettings'; 2 | export * from './PickerBaseProps'; 3 | export * from './DatePickerValue'; 4 | export * from './GeneralTypes'; 5 | -------------------------------------------------------------------------------- /src/components/MonthLevel/index.ts: -------------------------------------------------------------------------------- 1 | export { MonthLevel } from './MonthLevel'; 2 | export type { MonthLevelProps, MonthLevelStylesNames, MonthLevelSettings } from './MonthLevel'; 3 | -------------------------------------------------------------------------------- /src/components/MonthsList/index.ts: -------------------------------------------------------------------------------- 1 | export { MonthsList } from './MonthsList'; 2 | export type { MonthsListProps, MonthsListSettings, MonthsListStylesNames } from './MonthsList'; 3 | -------------------------------------------------------------------------------- /src/components/PickerControl/index.ts: -------------------------------------------------------------------------------- 1 | export { PickerControl } from './PickerControl'; 2 | export type { PickerControlProps, PickerControlStylesNames } from './PickerControl'; 3 | -------------------------------------------------------------------------------- /src/components/DateTimePicker/index.ts: -------------------------------------------------------------------------------- 1 | export { DateTimePicker } from './DateTimePicker'; 2 | export type { DateTimePickerProps, DateTimePickerStylesNames } from './DateTimePicker'; 3 | -------------------------------------------------------------------------------- /src/components/DecadeLevel/index.ts: -------------------------------------------------------------------------------- 1 | export { DecadeLevel } from './DecadeLevel'; 2 | export type { DecadeLevelProps, DecadeLevelSettings, DecadeLevelStylesNames } from './DecadeLevel'; 3 | -------------------------------------------------------------------------------- /src/components/YearLevelGroup/index.ts: -------------------------------------------------------------------------------- 1 | export { YearLevelGroup } from './YearLevelGroup'; 2 | export type { YearLevelGroupStylesNames, YearLevelGroupProps } from './YearLevelGroup'; 3 | -------------------------------------------------------------------------------- /.config/.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../../src/**/*.story.@(js|jsx|ts|tsx)'], 3 | addons: ['storybook-dark-mode'], 4 | framework: '@storybook/react', 5 | }; 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true -------------------------------------------------------------------------------- /src/components/DatePickerInput/index.ts: -------------------------------------------------------------------------------- 1 | export { DatePickerInput } from './DatePickerInput'; 2 | export type { DatePickerInputProps, DatePickerInputStylesNames } from './DatePickerInput'; 3 | -------------------------------------------------------------------------------- /src/components/HiddenDatesInput/index.ts: -------------------------------------------------------------------------------- 1 | export { HiddenDatesInput } from './HiddenDatesInput'; 2 | export type { HiddenDatesInputProps, HiddenDatesInputValue } from './HiddenDatesInput'; 3 | -------------------------------------------------------------------------------- /src/components/MonthLevelGroup/index.ts: -------------------------------------------------------------------------------- 1 | export { MonthLevelGroup } from './MonthLevelGroup'; 2 | export type { MonthLevelGroupProps, MonthLevelGroupStylesNames } from './MonthLevelGroup'; 3 | -------------------------------------------------------------------------------- /src/components/YearPickerInput/index.ts: -------------------------------------------------------------------------------- 1 | export { YearPickerInput } from './YearPickerInput'; 2 | export type { YearPickerInputProps, YearPickerInputStylesNames } from './YearPickerInput'; 3 | -------------------------------------------------------------------------------- /src/components/DecadeLevelGroup/index.ts: -------------------------------------------------------------------------------- 1 | export { DecadeLevelGroup } from './DecadeLevelGroup'; 2 | export type { DecadeLevelGroupProps, DecadeLevelGroupStylesNames } from './DecadeLevelGroup'; 3 | -------------------------------------------------------------------------------- /src/components/MonthPickerInput/index.ts: -------------------------------------------------------------------------------- 1 | export { MonthPickerInput } from './MonthPickerInput'; 2 | export type { MonthPickerInputProps, MonthPickerInputStylesNames } from './MonthPickerInput'; 3 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { getFormattedDate } from './get-formatted-date'; 2 | export { handleControlKeyDown } from './handle-control-key-down'; 3 | export { assignTime } from './assign-time/assign-time'; 4 | -------------------------------------------------------------------------------- /src/components/Calendar/Calendar.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles(() => ({ 4 | calendar: {}, 5 | calendarRtl: { 6 | direction: 'rtl', 7 | }, 8 | })); 9 | -------------------------------------------------------------------------------- /jest.setup.js: -------------------------------------------------------------------------------- 1 | require('@testing-library/jest-dom/extend-expect'); 2 | 3 | class ResizeObserver { 4 | observe() {} 5 | unobserve() {} 6 | disconnect() {} 7 | } 8 | 9 | window.ResizeObserver = ResizeObserver; 10 | -------------------------------------------------------------------------------- /src/components/CalendarHeader/index.ts: -------------------------------------------------------------------------------- 1 | export { CalendarHeader } from './CalendarHeader'; 2 | export type { 3 | CalendarHeaderProps, 4 | CalendarHeaderStylesNames, 5 | CalendarHeaderSettings, 6 | } from './CalendarHeader'; 7 | -------------------------------------------------------------------------------- /src/components/PickerInputBase/index.ts: -------------------------------------------------------------------------------- 1 | export { PickerInputBase } from './PickerInputBase'; 2 | export type { 3 | DateInputSharedProps, 4 | PickerInputBaseProps, 5 | PickerInputBaseStylesNames, 6 | } from './PickerInputBase'; 7 | -------------------------------------------------------------------------------- /scripts/nojekyll.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { fileURLToPath } from 'url'; 4 | 5 | fs.writeFileSync( 6 | path.join(path.dirname(fileURLToPath(import.meta.url)), '../docs/out/.nojekyll'), 7 | '' 8 | ); 9 | -------------------------------------------------------------------------------- /src/components/WeekdaysRow/index.ts: -------------------------------------------------------------------------------- 1 | export { WeekdaysRow } from './WeekdaysRow'; 2 | export { getWeekdayNames } from './get-weekdays-names/get-weekdays-names'; 3 | 4 | export type { WeekdaysRowProps, WeekdaysRowStylesNames } from './WeekdaysRow'; 5 | -------------------------------------------------------------------------------- /src/components/YearLevelGroup/YearLevelGroup.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | yearLevelGroup: { 5 | display: 'flex', 6 | gap: theme.spacing.md, 7 | }, 8 | })); 9 | -------------------------------------------------------------------------------- /src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useDatesState } from './use-dates-state/use-dates-state'; 2 | export { useDatesInput } from './use-dates-input/use-dates-input'; 3 | export { useUncontrolledDates } from './use-uncontrolled-dates/use-uncontrolled-dates'; 4 | -------------------------------------------------------------------------------- /src/components/MonthLevelGroup/MonthLevelGroup.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | monthLevelGroup: { 5 | display: 'flex', 6 | gap: theme.spacing.md, 7 | }, 8 | })); 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['mantine'], 3 | rules: { 4 | 'import/extensions': 'off', 5 | 'import/no-relative-packages': 'off', 6 | }, 7 | parserOptions: { 8 | project: './tsconfig.eslint.json', 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /src/components/DecadeLevelGroup/DecadeLevelGroup.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | decadeLevelGroup: { 5 | display: 'flex', 6 | gap: theme.spacing.md, 7 | }, 8 | })); 9 | -------------------------------------------------------------------------------- /src/components/DatesProvider/index.ts: -------------------------------------------------------------------------------- 1 | export { DATES_PROVIDER_DEFAULT_SETTINGS, DatesProvider } from './DatesProvider'; 2 | export { useDatesContext } from './use-dates-context'; 3 | export type { DatesProviderProps, DatesProviderSettings } from './DatesProvider'; 4 | -------------------------------------------------------------------------------- /src/types/GeneralTypes.ts: -------------------------------------------------------------------------------- 1 | export type DayOfWeek = 0 | 1 | 2 | 3 | 4 | 5 | 6; 2 | export type CalendarLevel = 'month' | 'year' | 'decade'; 3 | 4 | export interface ControlKeydownPayload { 5 | cellIndex: number; 6 | rowIndex: number; 7 | date: Date; 8 | } 9 | -------------------------------------------------------------------------------- /src/components/Month/is-before-max-date/is-before-max-date.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs'; 2 | 3 | export function isBeforeMaxDate(date: Date, maxDate?: Date) { 4 | return maxDate instanceof Date ? dayjs(date).isBefore(dayjs(maxDate).add(1, 'day'), 'day') : true; 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | *.log 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 7 | node_modules/ 8 | *.tsbuildinfo 9 | .npm 10 | .eslintcache 11 | .node_repl_history 12 | .yarn-integrity 13 | declarations 14 | dist 15 | .DS_Store 16 | -------------------------------------------------------------------------------- /src/components/Month/is-after-min-date/is-after-min-date.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs'; 2 | 3 | export function isAfterMinDate(date: Date, minDate?: Date) { 4 | return minDate instanceof Date 5 | ? dayjs(date).isAfter(dayjs(minDate).subtract(1, 'day'), 'day') 6 | : true; 7 | } 8 | -------------------------------------------------------------------------------- /src/components/YearLevel/YearLevel.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | yearLevel: { 5 | width: 252, 6 | }, 7 | 8 | calendarHeader: { 9 | marginBottom: theme.spacing.xs, 10 | }, 11 | })); 12 | -------------------------------------------------------------------------------- /src/components/DecadeLevel/DecadeLevel.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | decadeLevel: { 5 | width: 252, 6 | }, 7 | 8 | calendarHeader: { 9 | marginBottom: theme.spacing.xs, 10 | }, 11 | })); 12 | -------------------------------------------------------------------------------- /src/components/MonthLevel/MonthLevel.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | monthLevel: { 5 | width: 252, 6 | }, 7 | 8 | calendarHeader: { 9 | marginBottom: theme.spacing.xs, 10 | }, 11 | })); 12 | -------------------------------------------------------------------------------- /src/components/DecadeLevel/get-decade-range/get-decade-range.ts: -------------------------------------------------------------------------------- 1 | import { getYearsData } from '../../YearsList/get-years-data/get-years-data'; 2 | 3 | export function getDecadeRange(decade: Date) { 4 | const years = getYearsData(decade); 5 | return [years[0][0], years[3][0]] as const; 6 | } 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | logs 2 | *.log 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 7 | node_modules/ 8 | *.tsbuildinfo 9 | .npm 10 | .eslintcache 11 | .node_repl_history 12 | .yarn-integrity 13 | src 14 | scripts 15 | yarn.lock 16 | .config 17 | docs 18 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], 3 | testEnvironment: 'jsdom', 4 | testMatch: ['**/?(*.)+(spec|test).ts?(x)'], 5 | setupFilesAfterEnv: ['/jest.setup.js'], 6 | transform: { 7 | '^.+\\.tsx?$': 'ts-jest', 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /src/components/DateTimePicker/DateTimePicker.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | timeWrapper: { 5 | display: 'flex', 6 | marginTop: theme.spacing.md, 7 | }, 8 | 9 | timeInput: { 10 | flex: 1, 11 | marginRight: theme.spacing.md, 12 | }, 13 | })); 14 | -------------------------------------------------------------------------------- /src/components/YearsList/YearsList.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles(() => ({ 4 | yearsList: { 5 | width: '100%', 6 | borderCollapse: 'collapse', 7 | borderWidth: 0, 8 | }, 9 | 10 | yearsListCell: { 11 | padding: 0.5, 12 | }, 13 | 14 | yearsListRow: {}, 15 | })); 16 | -------------------------------------------------------------------------------- /src/components/MonthsList/MonthsList.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles(() => ({ 4 | monthsList: { 5 | width: '100%', 6 | borderCollapse: 'collapse', 7 | borderWidth: 0, 8 | }, 9 | 10 | monthsListCell: { 11 | padding: 0.5, 12 | }, 13 | 14 | monthsListRow: {}, 15 | })); 16 | -------------------------------------------------------------------------------- /src/components/Calendar/index.ts: -------------------------------------------------------------------------------- 1 | export { Calendar } from './Calendar'; 2 | export { pickCalendarProps } from './pick-calendar-levels-props/pick-calendar-levels-props'; 3 | export type { 4 | CalendarSettings, 5 | CalendarAriaLabels, 6 | CalendarProps, 7 | CalendarStylesNames, 8 | CalendarBaseProps, 9 | CalendarSystemProps, 10 | } from './Calendar'; 11 | -------------------------------------------------------------------------------- /src/components/Month/get-start-of-week/get-start-of-week.ts: -------------------------------------------------------------------------------- 1 | import type { DayOfWeek } from '../../../types'; 2 | 3 | export function getStartOfWeek(date: Date, firstDayOfWeek: DayOfWeek = 1) { 4 | const value = new Date(date); 5 | 6 | while (value.getDay() !== firstDayOfWeek) { 7 | value.setDate(value.getDate() - 1); 8 | } 9 | 10 | return value; 11 | } 12 | -------------------------------------------------------------------------------- /src/types/DatePickerValue.ts: -------------------------------------------------------------------------------- 1 | export type DateValue = Date | null; 2 | export type DatesRangeValue = [DateValue, DateValue]; 3 | export type DatePickerType = 'default' | 'multiple' | 'range'; 4 | 5 | export type DatePickerValue = Type extends 'range' 6 | ? DatesRangeValue 7 | : Type extends 'multiple' 8 | ? Date[] 9 | : DateValue; 10 | -------------------------------------------------------------------------------- /docs/pages/date-input.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # DateInput component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /docs/pages/time-input.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # TimeInput component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /docs/pages/date-picker.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # DatePicker component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /docs/pages/year-picker.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # YearPicker component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /docs/pages/month-picker.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # MonthPicker component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /docs/pages/date-time-picker.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # DateTimePicker component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /docs/pages/date-picker-input.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # DatePickerInput component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /docs/pages/year-picker-input.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # YearPickerInput component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /src/components/Month/index.ts: -------------------------------------------------------------------------------- 1 | export { getEndOfWeek } from './get-end-of-week/get-end-of-week'; 2 | export { getStartOfWeek } from './get-start-of-week/get-start-of-week'; 3 | export { getMonthDays } from './get-month-days/get-month-days'; 4 | export { isSameMonth } from './is-same-month/is-same-month'; 5 | 6 | export { Month } from './Month'; 7 | export type { MonthProps, MonthSettings, MonthStylesNames } from './Month'; 8 | -------------------------------------------------------------------------------- /docs/pages/month-picker-input.mdx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mantine/core'; 2 | import { PropsTable } from '../components/PropsTable/PropsTable.tsx'; 3 | import * as Demos from '../demos'; 4 | 5 | # MonthPickerInput component 6 | 7 | 8 | 9 | 10 | 11 | export default ({ children }) => {children}; 12 | -------------------------------------------------------------------------------- /docs/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Container } from '@mantine/core'; 3 | import { PageHeader } from '../components/PageHeader/PageHeader'; 4 | import HomePageContent from '../mdx/home-page.mdx'; 5 | 6 | export default function HomePage() { 7 | return ( 8 |
9 | 10 | 11 | 12 | 13 | 14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/components/Month/get-end-of-week/get-end-of-week.ts: -------------------------------------------------------------------------------- 1 | import type { DayOfWeek } from '../../../types'; 2 | 3 | export function getEndOfWeek(date: Date, firstDayOfWeek: DayOfWeek = 1) { 4 | const value = new Date(date); 5 | const lastDayOfWeek = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1; 6 | 7 | while (value.getDay() !== lastDayOfWeek) { 8 | value.setDate(value.getDate() + 1); 9 | } 10 | 11 | return value; 12 | } 13 | -------------------------------------------------------------------------------- /src/components/WeekdaysRow/WeekdaysRow.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | weekdaysRow: {}, 5 | weekday: { 6 | color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[5], 7 | fontWeight: 400, 8 | fontSize: theme.fontSizes.sm, 9 | textTransform: 'capitalize', 10 | paddingBottom: theme.spacing.xs / 2, 11 | }, 12 | })); 13 | -------------------------------------------------------------------------------- /src/components/DecadeLevel/get-decade-range/get-decade-range.test.ts: -------------------------------------------------------------------------------- 1 | import { getDecadeRange } from './get-decade-range'; 2 | 3 | describe('@mantine/dates/get-decades-range', () => { 4 | it('returns correct range based on given date', () => { 5 | expect(getDecadeRange(new Date(2022, 0))).toStrictEqual([new Date(2020, 0), new Date(2029, 0)]); 6 | expect(getDecadeRange(new Date(2011, 0))).toStrictEqual([new Date(2010, 0), new Date(2019, 0)]); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /src/components/YearsList/is-year-disabled/is-year-disabled.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs'; 2 | 3 | export function isYearDisabled(year: Date, minDate: Date, maxDate: Date) { 4 | if (!minDate && !maxDate) { 5 | return false; 6 | } 7 | 8 | if (minDate && dayjs(year).isBefore(minDate, 'year')) { 9 | return true; 10 | } 11 | 12 | if (maxDate && dayjs(year).isAfter(maxDate, 'year')) { 13 | return true; 14 | } 15 | 16 | return false; 17 | } 18 | -------------------------------------------------------------------------------- /src/components/Month/Month.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | monthThead: {}, 5 | monthRow: {}, 6 | monthTbody: {}, 7 | 8 | monthCell: { 9 | padding: 0.5, 10 | }, 11 | 12 | month: { 13 | ...theme.fn.fontStyles(), 14 | borderCollapse: 'collapse', 15 | tableLayout: 'fixed', 16 | 17 | '& *': { 18 | boxSizing: 'border-box', 19 | }, 20 | }, 21 | })); 22 | -------------------------------------------------------------------------------- /src/components/Month/is-same-month/is-same-month.test.ts: -------------------------------------------------------------------------------- 1 | import { isSameMonth } from './is-same-month'; 2 | 3 | describe('@mantine/dates/is-same-month', () => { 4 | it('detects same month', () => { 5 | expect(isSameMonth(new Date(2021, 2, 1), new Date(2021, 2, 2))).toBe(true); 6 | expect(isSameMonth(new Date(2021, 3, 1), new Date(2021, 2, 2))).toBe(false); 7 | expect(isSameMonth(new Date(2022, 2, 2), new Date(2021, 2, 2))).toBe(false); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /src/components/MonthsList/is-month-disabled/is-month-disabled.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs'; 2 | 3 | export function isMonthDisabled(month: Date, minDate: Date, maxDate: Date) { 4 | if (!minDate && !maxDate) { 5 | return false; 6 | } 7 | 8 | if (minDate && dayjs(month).isBefore(minDate, 'month')) { 9 | return true; 10 | } 11 | 12 | if (maxDate && dayjs(month).isAfter(maxDate, 'month')) { 13 | return true; 14 | } 15 | 16 | return false; 17 | } 18 | -------------------------------------------------------------------------------- /docs/components/PageHeader/PageHeader.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | root: { 5 | paddingTop: 80, 6 | paddingBottom: 50, 7 | backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.gray[0], 8 | }, 9 | 10 | title: { 11 | color: theme.colorScheme === 'dark' ? theme.white : theme.black, 12 | }, 13 | 14 | description: { 15 | maxWidth: 500, 16 | }, 17 | })); 18 | -------------------------------------------------------------------------------- /docs/components/MdxProvider/MdxPrism/MdxPrism.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Prism } from '@mantine/prism'; 3 | 4 | export function MdxPrism(props: any) { 5 | const matches = (props.children.props.className || '').match(/language-(?.*)/); 6 | 7 | return ( 8 | 12 | {props.children.props.children} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/components/PickerInputBase/PickerInputBase.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | placeholder: { 5 | opacity: 1, 6 | userSelect: 'none', 7 | color: theme.colorScheme === 'dark' ? theme.colors.dark[3] : theme.colors.gray[5], 8 | }, 9 | 10 | input: { 11 | cursor: 'pointer', 12 | lineHeight: 'unset', 13 | 14 | '&[data-read-only]': { 15 | cursor: 'default', 16 | }, 17 | }, 18 | })); 19 | -------------------------------------------------------------------------------- /src/components/TimeInput/TimeInput.story.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TimeInput } from './TimeInput'; 3 | 4 | export default { title: 'TimeInput' }; 5 | 6 | export function Usage() { 7 | return ( 8 |
9 | 10 |
11 | ); 12 | } 13 | 14 | export function WithSeconds() { 15 | return ( 16 |
17 | 18 |
19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "target": "ES2015", 5 | "lib": ["DOM", "ESNext"], 6 | "module": "ESNext", 7 | "moduleResolution": "Node", 8 | "jsx": "react", 9 | "skipLibCheck": true, 10 | "outDir": "temp", 11 | "declaration": true, 12 | "declarationMap": true, 13 | "resolveJsonModule": true, 14 | "declarationDir": "declarations", 15 | "allowSyntheticDefaultImports": true, 16 | "esModuleInterop": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/components/PageHeader/LinkItem/LinkItem.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | wrapper: { 5 | display: 'flex', 6 | alignItems: 'center', 7 | }, 8 | 9 | link: { 10 | color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.gray[9], 11 | display: 'flex', 12 | alignItems: 'center', 13 | lineHeight: 1, 14 | }, 15 | 16 | icon: { 17 | marginRight: 12, 18 | display: 'flex', 19 | alignItems: 'center', 20 | }, 21 | })); 22 | -------------------------------------------------------------------------------- /src/components/MonthsList/get-months-data/get-months-data.ts: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs'; 2 | 3 | export function getMonthsData(year: Date) { 4 | const startOfYear = dayjs(year).startOf('year').toDate(); 5 | 6 | const results: Date[][] = [[], [], [], []]; 7 | let currentMonthIndex = 0; 8 | 9 | for (let i = 0; i < 4; i += 1) { 10 | for (let j = 0; j < 3; j += 1) { 11 | results[i].push(dayjs(startOfYear).add(currentMonthIndex, 'months').toDate()); 12 | currentMonthIndex += 1; 13 | } 14 | } 15 | 16 | return results; 17 | } 18 | -------------------------------------------------------------------------------- /src/components/YearsList/get-years-data/get-years-data.ts: -------------------------------------------------------------------------------- 1 | export function getYearsData(decade: Date) { 2 | const year = decade.getFullYear(); 3 | 4 | const rounded = year - (year % 10); 5 | 6 | let currentYearIndex = 0; 7 | const results: Date[][] = [[], [], [], []]; 8 | 9 | for (let i = 0; i < 4; i += 1) { 10 | const max = i === 3 ? 1 : 3; 11 | for (let j = 0; j < max; j += 1) { 12 | results[i].push(new Date(rounded + currentYearIndex, 0)); 13 | currentYearIndex += 1; 14 | } 15 | } 16 | 17 | return results; 18 | } 19 | -------------------------------------------------------------------------------- /docs/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createGetInitialProps } from '@mantine/next'; 3 | import Document, { Head, Html, Main, NextScript } from 'next/document'; 4 | 5 | const getInitialProps = createGetInitialProps(); 6 | 7 | export default class _Document extends Document { 8 | static getInitialProps = getInitialProps; 9 | 10 | render() { 11 | return ( 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /scripts/update-version.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra'; 2 | import path from 'path'; 3 | import { fileURLToPath } from 'url'; 4 | import pkg from '../package.json'; 5 | import { getNextVersion } from './get-next-version'; 6 | 7 | export function updateVersion(config: { type: string; stage?: string }) { 8 | const nextVersion = getNextVersion(pkg.version, config); 9 | pkg.version = nextVersion; 10 | fs.writeJsonSync( 11 | path.join(path.dirname(fileURLToPath(import.meta.url)), '../package.json'), 12 | pkg, 13 | { spaces: 2 } 14 | ); 15 | return pkg; 16 | } 17 | -------------------------------------------------------------------------------- /docs/components/MdxProvider/MdxTitle/MdxTitle.styles.ts: -------------------------------------------------------------------------------- 1 | import { createStyles } from '@mantine/core'; 2 | 3 | export default createStyles((theme) => ({ 4 | title: { 5 | marginTop: theme.spacing.xl * 1.2, 6 | marginBottom: theme.spacing.md, 7 | wordBreak: 'break-word', 8 | color: theme.colorScheme === 'dark' ? theme.white : theme.black, 9 | }, 10 | 11 | link: { 12 | ...theme.fn.focusStyles(), 13 | textDecoration: 'none', 14 | color: 'inherit', 15 | }, 16 | 17 | offset: { 18 | position: 'relative', 19 | top: -62, 20 | }, 21 | })); 22 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | docgen.json 38 | .DS_Store 39 | -------------------------------------------------------------------------------- /src/utils/assign-time/assign-time.ts: -------------------------------------------------------------------------------- 1 | export function assignTime(originalDate: Date, resultDate: Date) { 2 | if (!originalDate || !resultDate) { 3 | return resultDate; 4 | } 5 | 6 | const hours = originalDate.getHours(); 7 | const minutes = originalDate.getMinutes(); 8 | const seconds = originalDate.getSeconds(); 9 | const ms = originalDate.getMilliseconds(); 10 | 11 | const result = new Date(resultDate); 12 | result.setHours(hours); 13 | result.setMinutes(minutes); 14 | result.setSeconds(seconds); 15 | result.setMilliseconds(ms); 16 | 17 | return result; 18 | } 19 | -------------------------------------------------------------------------------- /docs/components/Shell/Shell.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AppShell } from '@mantine/core'; 3 | import { Header } from './Header'; 4 | import { Footer } from './Footer'; 5 | 6 | interface ShellProps { 7 | children: React.ReactNode; 8 | } 9 | 10 | export function Shell({ children }: ShellProps) { 11 | return ( 12 | } 14 | footer={