vjndatepicker 0.0.0-stage → 0.3.16
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/CHANGELOG.md +124 -0
- package/LICENSE +5 -0
- package/README.fa.md +253 -0
- package/README.md +65 -2
- package/dist/core/index.cjs +716 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +205 -0
- package/dist/core/index.d.ts +205 -0
- package/dist/core/index.js +658 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.cjs +2509 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +482 -0
- package/dist/index.d.ts +482 -0
- package/dist/index.js +2403 -0
- package/dist/index.js.map +1 -0
- package/docs/DEVICE-TESTS.fa.md +29 -0
- package/docs/EVENTS.fa.md +72 -0
- package/docs/RANGE-CONTRACT.fa.md +63 -0
- package/docs/VALIDATION.md +53 -0
- package/package.json +95 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.16
|
|
4
|
+
|
|
5
|
+
- Give the mobile year-only picker a focused, single-column wheel with a fixed 12px selected surface, readable numeric hierarchy and no redundant view toggle.
|
|
6
|
+
- Refine the desktop year grid with fixed 12px targets, calmer inactive states, visible keyboard focus and an explicit ascending left-to-right numeric order in RTL and LTR layouts.
|
|
7
|
+
|
|
8
|
+
## 0.3.15
|
|
9
|
+
|
|
10
|
+
- Refine every picker footer with a fixed 12px radius that is visually aligned with the calendar panel, including icon actions and the composed date-time range.
|
|
11
|
+
- Give utility icons a subtle surface and border, use an outlined Cancel action, and improve footer spacing, hover, focus and disabled states without inheriting oversized consumer theme radii.
|
|
12
|
+
|
|
13
|
+
## 0.3.14
|
|
14
|
+
|
|
15
|
+
- Share square, 40px footer actions across popup, inline and composed datetime-range controls; add `slotProps.actions.sx` and `slotProps.actionButton.sx` overrides.
|
|
16
|
+
- Apply on-blur validation to composed datetime ranges, retain immediate validation and explicit form errors, and reset visual validation state on native reset/cancel. Actual invalid values still block acceptance.
|
|
17
|
+
- Cover both calendars at month and year boundaries with range/event, bounds, keyboard, touch and controlled-value regression tests.
|
|
18
|
+
- Add Chromium, Firefox and WebKit interaction tests, isolated installed-tarball MUI 5.6/9.4 browser checks, and opt-in screenshot comparisons with reviewed OS-specific baselines.
|
|
19
|
+
- Gate CI publication on browser compatibility and Windows visual regression jobs. Physical-device, screen-reader and remote CI results remain separately recorded in `docs/VALIDATION.md`.
|
|
20
|
+
|
|
21
|
+
## 0.3.13
|
|
22
|
+
|
|
23
|
+
- Remove all corner rounding from picker footer buttons, including icon actions and Cancel/Apply, even with rounded consumer themes.
|
|
24
|
+
|
|
25
|
+
## 0.3.12
|
|
26
|
+
|
|
27
|
+
- Align picker footer buttons to a consistent 40px height with 8px corners and spacing, independent of consumer theme spacing and shape multipliers.
|
|
28
|
+
- Group utility and confirmation actions, explicitly apply the picker direction, and use a quiet text Cancel button alongside the primary Apply button.
|
|
29
|
+
- Preserve actionDisplay/actionIcons options and theme colors/fonts; verify MUI 9.4 consumer button overrides in RTL and LTR.
|
|
30
|
+
|
|
31
|
+
## 0.3.11
|
|
32
|
+
|
|
33
|
+
- Do not render untouched required picker fields as invalid on a new form; internal validation now appears after the control loses focus.
|
|
34
|
+
- Add configurable `validationMode="onBlur" | "immediate"`, defaulting to `onBlur`; explicit consumer `error` remains immediate.
|
|
35
|
+
- Keep ref `validate()` independent from visual touched state and deduplicate `onError` transitions.
|
|
36
|
+
|
|
37
|
+
## 0.3.10
|
|
38
|
+
|
|
39
|
+
- Formalize wheel-first mobile behavior: year-only has one wheel, month-only has one wheel, year-month has two wheels, and full dates have three.
|
|
40
|
+
- Size one- and two-column wheels to focused mobile widths instead of stretching a single choice across the sheet.
|
|
41
|
+
- Keep `mobileMode="calendar"` as the explicit per-picker or provider override and add regression coverage for every column contract.
|
|
42
|
+
|
|
43
|
+
## 0.3.9
|
|
44
|
+
|
|
45
|
+
- Stabilize adjacent-month range selection: an earlier second click restarts the range, while same-day ranges remain valid.
|
|
46
|
+
- Add `rangeEndBehavior="swap"` for compatibility with the former endpoint-swapping behavior.
|
|
47
|
+
- Add `onRangeChange`, emitted once immediately after `onChange` for each changed stored range.
|
|
48
|
+
- Add executable two-month Jalali contract example and automated month/year crossing, touch, keyboard, controlled-value, disabled-date, RTL digit and consumer-font coverage.
|
|
49
|
+
|
|
50
|
+
## 0.3.8
|
|
51
|
+
|
|
52
|
+
- Replace the input's raw `×` character with a consistent SVG close icon.
|
|
53
|
+
- Isolate field action buttons from consumer IconButton backgrounds; default is transparent with a subtle hover state.
|
|
54
|
+
- Add `field.clearIcon` customization and remove an invalid textbox `aria-expanded` attribute detected by browser accessibility auditing.
|
|
55
|
+
|
|
56
|
+
## 0.3.7
|
|
57
|
+
|
|
58
|
+
- Reduce desktop picker surface radius from 24px to 16px and month/year targets from 18px to 12px.
|
|
59
|
+
- Reduce navigation, summary and action-button rounding for a cleaner, less inflated visual hierarchy.
|
|
60
|
+
- Keep radius customization available through `slotProps.panel.sx` and inline calendar `sx`.
|
|
61
|
+
|
|
62
|
+
## 0.3.6
|
|
63
|
+
|
|
64
|
+
- Replace the crowded default action bar with a professional minimal layout: icon-only Today/Clear with tooltips and textual Cancel/Accept actions.
|
|
65
|
+
- Add globally configurable `actionDisplay` modes: `minimal`, `text`, `icon-text`, and `icons`.
|
|
66
|
+
- Refresh the built-in clear icon and preserve per-action icon replacement/opt-out behavior.
|
|
67
|
+
|
|
68
|
+
## 0.3.5
|
|
69
|
+
|
|
70
|
+
- Keep Jalali month rows RTL while rendering numeric year rows in ascending left-to-right order.
|
|
71
|
+
- Make Jalali title alignment resilient to MUI RTL style transformations by using logical inline alignment.
|
|
72
|
+
- Refine navigation, selection surfaces and the action bar; desktop actions now remain on one compact row.
|
|
73
|
+
|
|
74
|
+
## 0.3.4
|
|
75
|
+
|
|
76
|
+
- Fix month and year chooser ordering under consumer RTL themes, placing the first Jalali month/year at the right edge of each row.
|
|
77
|
+
- Refresh month/year selection surfaces with compact rows, rounded targets, clearer selection and hover elevation.
|
|
78
|
+
- Right-align Jalali titles explicitly and omit the redundant empty `انتخاب تاریخ` subtitle.
|
|
79
|
+
- Add built-in action icons for Today, Clear, Cancel and Accept with per-picker `actionIcons` customization or opt-out.
|
|
80
|
+
|
|
81
|
+
## 0.3.3
|
|
82
|
+
|
|
83
|
+
- Make Persian weekday and date-cell placement deterministic under consumer RTL themes instead of relying on inherited CSS direction.
|
|
84
|
+
- Prevent host RTL icon transforms from mirroring the month navigation chevrons.
|
|
85
|
+
- Reduce desktop header and calendar-navigation whitespace for a more compact popover.
|
|
86
|
+
|
|
87
|
+
## 0.3.2
|
|
88
|
+
|
|
89
|
+
- Pin Persian calendar rows to RTL so Saturday is always the rightmost day and Friday the leftmost day, including inside portals.
|
|
90
|
+
- Place previous/next controls explicitly for RTL and give each arrow an unambiguous semantic direction.
|
|
91
|
+
- Refine navigation spacing, weekday emphasis and circular day targets for a cleaner, more consistent calendar UI.
|
|
92
|
+
- Keep optional week numbers on the outer edge in both RTL and LTR layouts.
|
|
93
|
+
|
|
94
|
+
## 0.3.1
|
|
95
|
+
|
|
96
|
+
- Support MUI 5.6 through 9 with version-aware TextField, Drawer and Popover slot properties.
|
|
97
|
+
- Broaden peer dependencies to React 18/19 and the compatible Emotion 11 range.
|
|
98
|
+
- Verify type checking, UI behavior and package output against both MUI 5.18 and MUI 9.4.
|
|
99
|
+
|
|
100
|
+
## 0.3.0
|
|
101
|
+
|
|
102
|
+
- 29 documented callbacks, actual controlled-open lifecycle, transition-only state events and change provenance.
|
|
103
|
+
- Dynamic disabled/readOnly closes the popup even if the controlling parent ignores its close request; staged values are discarded.
|
|
104
|
+
- Native reset and imperative reset/validate/end-field focus; disabled versus readonly FormData semantics.
|
|
105
|
+
- Controlled view/month/range position, calendar references, week numbers, compact weeks, hidden outside days and keyboard period navigation.
|
|
106
|
+
- Date allow/block lists, date-specific time availability, local date-time boundaries and 12-hour presentation with canonical HH:mm output.
|
|
107
|
+
- Custom typed input formatting/parsing and commit policies.
|
|
108
|
+
- Corrected provider settings filtering to prevent callbacks leaking into composed child controls.
|
|
109
|
+
- Real Chromium desktop/mobile smoke tests, automatic accessibility checks and screenshots.
|
|
110
|
+
|
|
111
|
+
## 0.2.0
|
|
112
|
+
|
|
113
|
+
- Shared multi-month grids and range highlighting, responsive counts, correct end-field opening, explicit endpoint selection.
|
|
114
|
+
- Real MUI text fields, strict Persian/Arabic/Latin manual entry, configurable icon/field/manual opening and independent clear action.
|
|
115
|
+
- Draft, input, range position, view, visible window, calendar switch, clear and cancel callbacks; deduplicated error reporting.
|
|
116
|
+
- Mobile vertical month windows, fullscreen sheets, sticky actions and cancel by dragging the handle.
|
|
117
|
+
- Caller-provided all-day/timed day events, counts, details, loading feedback and event click callbacks.
|
|
118
|
+
- Inline VjnCalendar, composed VjnDateTimeRangePicker, explicit IANA conversion and DST policy.
|
|
119
|
+
- Form focus scope, controlled open, public types, updated demo, installed lockfile, package consumer smoke.
|
|
120
|
+
- Full library and demo builds and executed UI tests. Real browser/device checks remain pending.
|
|
121
|
+
|
|
122
|
+
## 0.1.0
|
|
123
|
+
|
|
124
|
+
Initial source preview with core selection modes, date rules, Jalali/Gregorian conversion and mobile wheels.
|
package/LICENSE
ADDED
package/README.fa.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# vjndatepicker 0.3.16
|
|
2
|
+
|
|
3
|
+
کتابخانه React، TypeScript و MUI برای پروژههای Vjn؛ تقویم شمسی و میلادی، RTL، اعداد فارسی و خروجی استاندارد میلادی برای تاریخ کامل. فونت از Theme یا Provider پروژه مصرفکننده گرفته میشود؛ هیچ فونت، API، تعطیلی رسمی یا رویدادی از اینترنت دریافت نمیشود.
|
|
4
|
+
|
|
5
|
+
در نسخهٔ ۰٫۳٫۱۵ نوار دکمهها بین تمام انتخابگرها، از جمله بازهٔ تاریخوساعت، مشترک است. دکمهها و آیکونها شعاع ثابت ۱۲px دارند تا با پنل تقویم هماهنگ بمانند، حتی اگر `shape.borderRadius` تم مصرفکننده خیلی بزرگ باشد. تنظیم مستقیم ظاهر:
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<VjnDateTimeRangePicker
|
|
9
|
+
required
|
|
10
|
+
validationMode="onBlur"
|
|
11
|
+
slotProps={{
|
|
12
|
+
actions: { sx: { padding: '12px', gap: '8px' } },
|
|
13
|
+
actionButton: { sx: { borderRadius: '14px', height: '44px', minHeight: '44px' } },
|
|
14
|
+
}}
|
|
15
|
+
/>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
برای اندازه و گردی ثابت در `sx` از مقدار رشتهای مثل `'8px'` استفاده کنید؛ مقادیر عددی ممکن است با `spacing` یا `shape.borderRadius` تم مصرفکننده مقیاس شوند. `actionDisplay` و `actionIcons` همچنان قابل تنظیماند.
|
|
19
|
+
|
|
20
|
+
بازهٔ تاریخوساعت هم پیش از خروج فوکوس خطای الزامی نشان نمیدهد؛ `validationMode="immediate"` رفتار فوری را فعال میکند. مقدار نامعتبر حتی پیش از نمایش خطا قابل تأیید نیست. بازنشانی فرم و انصراف، وضعیت نمایش خطای داخلی را پاک میکنند. برای خطای هنگام ارسال فرم، مصرفکننده میتواند `error` و `helperText` را صریح ارسال کند.
|
|
21
|
+
|
|
22
|
+
نتایج واقعی آزمونها و محدودیتهای دستگاه و مرورگر در [گزارش اعتبارسنجی](docs/VALIDATION.md) ثبت شده است.
|
|
23
|
+
|
|
24
|
+
## اجرای سورس و نصب پکیج
|
|
25
|
+
|
|
26
|
+
Node.js >=22.12؛ React، MUI، MUI System و Emotion، peerDependency هستند و در خروجی کتابخانه بستهبندی نمیشوند. محدودهٔ اعلامشده MUI از 5.6 تا کمتر از 10 و React نسخهٔ 18/19 است. ماتریس تعاملی این نسخه روی MUI 5.6 با React 18 و MUI 9.4 با React 19 اجرا میشود؛ این به معنی آزمون جداگانهٔ تمام نسخههای میانی نیست.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cd vjndatepicker
|
|
30
|
+
npm ci
|
|
31
|
+
npm run dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
دمو: `http://localhost:5173`. برای استفاده از فایل نصب آماده در پروژه دیگر:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install ./vjndatepicker-0.3.14.tgz
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
مقصد انتشار بسته رجیستری خصوصی `https://npm.sajeddev.ir` است. فایل `.gitlab-ci.yml` بررسی، ساخت و انتشار با tag و متغیرهای `NPM_PUBLISH_REGISTRY` و `NPM_TOKEN` را دارد. tag باید با نسخه package.json مطابق باشد؛ مثلاً `v0.3.14`. انتشار به موفقیت تستهای مرورگر و تصویر وابسته است؛ جزئیات runner در گزارش اعتبارسنجی آمده است.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm run check
|
|
44
|
+
npm pack --ignore-scripts
|
|
45
|
+
node scripts/consumer-smoke.mjs
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`pack:local` بررسیها را اجرا میکند و سپس فایل tgz میسازد. `consumer-smoke.mjs` بسته را در یک پروژه موقت واقعاً نصب میکند و importهای ESM/CJS، مسیر `core` و رندر سمت سرور را بررسی میکند.
|
|
49
|
+
|
|
50
|
+
## کنترلهای قابل استفاده
|
|
51
|
+
|
|
52
|
+
| کنترل | مدل مقدار |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| VjnDatePicker | ISODate یا null |
|
|
55
|
+
| VjnDateRangePicker | `{ start: ISODate \| null, end: ISODate \| null }` یا null |
|
|
56
|
+
| VjnDateTimePicker | `{ date: ISODate, time: HH:mm }` یا null |
|
|
57
|
+
| VjnDateTimeRangePicker | `{ start: DateTimeValue \| null, end: DateTimeValue \| null }` یا null |
|
|
58
|
+
| VjnMultiDatePicker | آرایه تاریخهای ISO |
|
|
59
|
+
| VjnWeekPicker | ابتدا و انتهای هفته به ISO |
|
|
60
|
+
| VjnMonthPicker | `{ calendar, month }` |
|
|
61
|
+
| VjnYearPicker | `{ calendar, year }` |
|
|
62
|
+
| VjnYearMonthPicker | `{ calendar, year, month }` |
|
|
63
|
+
| VjnTimePicker | HH:mm یا null |
|
|
64
|
+
| VjnCalendar | تقویم داخل صفحه؛ همان مدل انتخاب متناسب با mode |
|
|
65
|
+
|
|
66
|
+
## نمونه بازه حرفهای
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { useState } from 'react';
|
|
70
|
+
import { VjnDatePickerProvider, VjnDateRangePicker, type DateRangeValue } from 'vjndatepicker';
|
|
71
|
+
|
|
72
|
+
export default function ReportFilter() {
|
|
73
|
+
const [value, setValue] = useState<DateRangeValue | null>(null);
|
|
74
|
+
return (
|
|
75
|
+
<VjnDatePickerProvider calendar="jalali" locale="fa" fontFamily="Vazirmatn, Tahoma, sans-serif">
|
|
76
|
+
<VjnDateRangePicker
|
|
77
|
+
label="بازه گزارش"
|
|
78
|
+
value={value}
|
|
79
|
+
onChange={setValue}
|
|
80
|
+
fieldLayout="split"
|
|
81
|
+
fromLabel="از تاریخ"
|
|
82
|
+
toLabel="تا تاریخ"
|
|
83
|
+
calendars={{ xs: 1, md: 2, xl: 3 }}
|
|
84
|
+
field={{ editable: true, openOn: 'icon', iconPosition: 'end' }}
|
|
85
|
+
mobile={{ presentation: 'bottom-sheet', rangeLayout: 'vertical-scroll', months: 3, stickyActions: true }}
|
|
86
|
+
minRangeDays={1}
|
|
87
|
+
maxRangeDays={31}
|
|
88
|
+
/>
|
|
89
|
+
</VjnDatePickerProvider>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
خروجی نمونه: `{ start: '2026-10-01', end: '2026-10-15' }`. تغییر تقویم، تاریخ کامل و انتخاب موقت را تغییر نمیدهد. ماه و سال مستقل، وابسته به تقویم هستند و تبدیل خودکار آنها معنی مشخصی ندارد؛ پروژه مصرفکننده سیاست تغییرشان را تعیین کند.
|
|
95
|
+
|
|
96
|
+
## چند ماه و موبایل
|
|
97
|
+
|
|
98
|
+
`calendars` عدد ۱ تا ۱۲ یا تنظیم واکنشگراست: xs زیر ۹۰۰، md از ۹۰۰ و xl از ۱۲۸۰ پیکسل. ماهها یک انتخاب و پیشنمایش مشترک دارند. در دسکتاپ، بازه بهصورت پیشفرض دو ماه و سایر کنترلها یک ماه نشان میدهند. تعداد ستونها متناسب با عرض محدود میشود؛ ماههای بیشتر در ردیفهای بعد قرار میگیرند.
|
|
99
|
+
|
|
100
|
+
در موبایل، `mobile.months` تعداد ماههای هر پنجره پیمایش را تعیین میکند. `vertical-scroll` ماهها را زیر هم و `paged` با چیدمان واکنشگرا نمایش میدهد. این نسخه تقویم بینهایت مجازیشده ندارد؛ برای ماههای بعد، دکمه پیمایش وجود دارد. دکمههای پایین بهصورت پیشفرض ثابتاند؛ `stickyActions: false` کل محتوا را قابل اسکرول میکند. `presentation: 'fullscreen'` ارتفاع کامل میدهد. کشیدن دستگیره به پایین انتخاب موقت را لغو میکند؛ `swipeToClose: false` این رفتار را خاموش میکند.
|
|
101
|
+
|
|
102
|
+
تاریخ تکی، دورهها و ساعت حالت چرخشی دارند؛ تأیید صریح لازم است. بازه، هفته و چندتاریخ از شبکه تقویم استفاده میکنند. نمای چرخشی یک کنترل وب است.
|
|
103
|
+
|
|
104
|
+
## ورودی و آیکن
|
|
105
|
+
|
|
106
|
+
دسکتاپ پیشفرض: قابل تایپ، بازشدن با آیکن. موبایل پیشفرض: غیرقابل تایپ و بازشدن با بدنه یا آیکن. `field.editable` این پیشفرض را تغییر میدهد. `editable: false` انتخاب با تقویم را ممنوع نمیکند؛ `readOnly` و `disabled` انتخاب را هم مسدود میکنند.
|
|
107
|
+
|
|
108
|
+
`field.openOn`: icon، field، both یا manual. حالت manual با `ref.current.open()` یا `open` کنترل میشود. آیکن تقویم با `field.icon` و آیکن پاککردن ورودی با `field.clearIcon` عوض میشود؛ `hideIcon` و `iconPosition` نیز در دسترساند. variant ورودی: outlined، filled، standard. کلیک پاککردن، تقویم را باز نمیکند.
|
|
109
|
+
|
|
110
|
+
چیدمان پیشفرض نوار عملیات مینیمال است: امروز و پاککردن بهصورت آیکن همراه Tooltip و انصراف و تأیید بهصورت متن نمایش داده میشوند. با `actionDisplay` میتوان حالت `minimal`، `text`، `icon-text` یا `icons` را انتخاب کرد. با `actionIcons={false}` همهٔ آیکنها حذف میشوند؛ با `actionIcons={{ today: <MyTodayIcon />, accept: false }}` نیز میتوان هر آیکن را جداگانه جایگزین یا مخفی کرد.
|
|
111
|
+
|
|
112
|
+
شعاع پنجرهٔ دسکتاپ بهصورت پیشفرض ۱۶ پیکسل است و با `slotProps={{ panel: { sx: { borderRadius: 1 } } }}` قابل تغییر است؛ اعداد MUI بر پایهٔ spacing تم محاسبه میشوند.
|
|
113
|
+
|
|
114
|
+
ورودی فارسی، عربی و لاتین پذیرفته میشود. Enter یا خروج فوکوس از فیلد، متن معتبر را ذخیره میکند؛ Escape متن را به مقدار ذخیرهشده برمیگرداند. تاریخ نامعتبر اصلاح خودکار نمیشود. در بازه دو فیلدی، سر اول موقت میماند تا سر دوم معتبر شود.
|
|
115
|
+
|
|
116
|
+
| حالت | قالب ورود دستی |
|
|
117
|
+
| --- | --- |
|
|
118
|
+
| تاریخ | YYYY/MM/DD یا YYYY-MM-DD در تقویم فعال |
|
|
119
|
+
| ساعت | HH:mm |
|
|
120
|
+
| تاریخ و ساعت | YYYY/MM/DD HH:mm |
|
|
121
|
+
| بازه تکفیلدی | YYYY/MM/DD — YYYY/MM/DD |
|
|
122
|
+
| هفته | یک تاریخ یا دو سر یک هفته معتبر |
|
|
123
|
+
| چندتاریخ | تاریخها با ویرگول فارسی/لاتین یا نقطهویرگول |
|
|
124
|
+
| ماه | عدد ماه |
|
|
125
|
+
| سال | سال چهاررقمی |
|
|
126
|
+
| سال و ماه | YYYY/MM |
|
|
127
|
+
|
|
128
|
+
## قرارداد Callbackها
|
|
129
|
+
|
|
130
|
+
| Callback | زمان اجرا |
|
|
131
|
+
| --- | --- |
|
|
132
|
+
| onInputChange(text, part) | تغییر متن خام؛ part برابر auto/start/end |
|
|
133
|
+
| onDraftChange(value, context) | تغییر انتخاب موقت؛ context شامل source، validationError و complete |
|
|
134
|
+
| onChange(value, context) | ذخیره مقدار تغییرکرده؛ reason برابر select/accept/input/clear |
|
|
135
|
+
| onRangeChange(value, context) | فقط در حالت range، همان مقدار نهایی را دقیقاً بعد از onChange اعلام میکند |
|
|
136
|
+
| onAccept(value) | تأیید موفق؛ حتی وقتی مقدار تغییر نکرده است |
|
|
137
|
+
| onOpen / onOpenChange | بازشدن واقعی پنجره / درخواست تغییر open |
|
|
138
|
+
| onClose(reason) | بستهشدن از اعمال کنترل؛ accept/cancel/escape/backdrop/clear |
|
|
139
|
+
| onCancel | انصراف، Escape، بیرون پنجره یا کشیدن دستگیره |
|
|
140
|
+
| onClear | پاککردن مستقل |
|
|
141
|
+
| onError | فقط تغییر وضعیت خطا، شامل بازگشت به null |
|
|
142
|
+
| onRangePositionChange | تغییر مرحله شروع/پایان |
|
|
143
|
+
| onViewChange | تغییر نمای day/month/year/wheel/time |
|
|
144
|
+
| onVisibleRangeChange | تغییر پنجره ماههای تقویم؛ مناسب دریافت داده از API پروژه |
|
|
145
|
+
| onCalendarChange | درخواست تغییر تقویم از دکمه داخلی |
|
|
146
|
+
| onEventClick(event, date) | کلیک رویداد در فهرست روز |
|
|
147
|
+
|
|
148
|
+
انتخاب موقت: onDraftChange. در range، تأیید مقدار متفاوت: onChange → onRangeChange → onAccept → onClose. انصراف: onCancel → onClose، بدون ذخیره. reason انتخاب خودکار دسکتاپ select و تأیید صریح accept است. source انتخاب موقت: calendar، wheel، input، shortcut، today، remove.
|
|
149
|
+
|
|
150
|
+
در انتخاب بازه، پایانِ قبل از شروع بهصورت پیشفرض شروع جدید میشود و پایان خالی میماند. برای حفظ رفتار نسخههای قدیمی که دو سر را جابهجا میکرد، `rangeEndBehavior="swap"` بدهید. قرارداد و ماتریس آزمون کامل در `docs/RANGE-CONTRACT.fa.md` ثبت شده است.
|
|
151
|
+
|
|
152
|
+
`open/defaultOpen/onOpenChange` و `value/defaultValue/onChange` کنترلشده یا داخلیاند؛ در حالت کنترلشده والد باید مقدار جدید را اعمال کند. `ref` متدهای open، close، clear، focus دارد. تغییر `open` مستقیم توسط والد نیز onOpen/onClose میدهد؛ علت بستهشدن مستقیم والد programmatic است. `onBlur` ورود فوکوس به پنجره تقویم را پایان تعامل فرم حساب نمیکند.
|
|
153
|
+
|
|
154
|
+
`showCalendarSwitch` دکمه شمسی/میلادی را نشان میدهد. اگر calendar صریح داده شده، onCalendarChange را به state والد متصل کنید.
|
|
155
|
+
|
|
156
|
+
## رویدادهای روز
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
const events = [
|
|
160
|
+
{ id: 'invoice-1', title: 'سررسید نمونه', allDay: true as const, start: '2026-10-05' as const, color: '#1976d2', metadata: { invoiceId: 1 } },
|
|
161
|
+
{ id: 'meeting-1', title: 'جلسه نمونه', allDay: false as const, start: '2026-10-06' as const, startTime: '09:30' as const, endTime: '10:30' as const },
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
<VjnDateRangePicker events={events} loading={loading} onVisibleRangeChange={handleVisibleRange} onEventClick={handleEvent} />
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
پروژه مصرفکننده داده واقعی را دریافت میکند و events/loading میدهد؛ خود پکیج شبکه یا Cache سرور ندارد. end رویداد، در صورت وجود، تاریخ انتهای شاملشونده است. ساعتها محلی و متعلق به تقویم داده مصرفکنندهاند. نشان تعداد، جزئیات روز را باز میکند و تاریخ را انتخاب نمیکند. وجود رویداد روز را غیرفعال نمیکند؛ Holiday و محدودیت روز مستقلاند. `CalendarEvent<T>` امکان metadata تایپشده دارد؛ Callback عمومی metadata را unknown میبیند و مصرفکننده آن را بررسی میکند. تکرار رویداد و ویرایش زمانبندی، API این DatePicker نیست.
|
|
168
|
+
|
|
169
|
+
## تقویم داخل صفحه و بازه ساعتدار
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
<VjnCalendar mode="range" calendars={3} value={range} onChange={setRange} />
|
|
173
|
+
<VjnDateTimeRangePicker value={dateTimeRange} onChange={setDateTimeRange} />
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
VjnCalendar input و Dialog ندارد. بازه تاریخوساعت کنترل مرکب تاریخ بازهای و دو ساعت است؛ تأیید نهایی کل بازه در پایین آن انجام میشود. ترتیب زمان در یک روز، محدودیت هر دو سر و روزهای ممنوع داخل بازه بررسی میشود.
|
|
177
|
+
|
|
178
|
+
## نمای موبایل
|
|
179
|
+
|
|
180
|
+
نمای اولیهٔ موبایل بهصورت پیشفرض چرخشی است. تعداد ستونها از نوع انتخابگر تعیین میشود: `VjnYearPicker` فقط سال، `VjnMonthPicker` فقط ماه، `VjnYearMonthPicker` سال و ماه، و تاریخ کامل سال و ماه و روز را نشان میدهد. چرخِ فقطسال یک نمای مستقل و متمرکز، با سال انتخابشده در مرکز دارد و کلید جابهجایی نمای اضافی نشان نمیدهد؛ برای درخواست صریح شبکهٔ سالها از `mobileMode="calendar"` و برای اجبار نمای چرخشی از `mobileMode="wheel"` استفاده کنید. این تنظیم روی خود انتخابگر یا `VjnDatePickerProvider` قابل تعریف است. در نمای شبکه، سالها همیشه بهترتیب صعودی از چپ به راست میآیند تا جهت RTL ترتیب عددی را معکوس نکند؛ این ترتیب در آزمون مرورگر نیز کنترل میشود.
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
<VjnYearPicker variant="mobile" />
|
|
184
|
+
<VjnYearMonthPicker variant="mobile" />
|
|
185
|
+
<VjnYearMonthPicker variant="mobile" mobileMode="calendar" />
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## منطقه زمانی
|
|
189
|
+
|
|
190
|
+
تاریخ بدون ساعت، ISO date-only میماند. خروجی ساعتدار، wall-clock محلی است. برای تبدیل صریح به instant:
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
import { dateTimeToInstant, instantToDateTime } from 'vjndatepicker/core';
|
|
194
|
+
const instant = dateTimeToInstant({ date: '2026-10-05', time: '08:00' }, 'Asia/Tehran');
|
|
195
|
+
// 2026-10-05T04:30:00.000Z
|
|
196
|
+
const local = instantToDateTime(instant, 'Asia/Tehran');
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
زمان ناموجود DST رد میشود. زمان مبهم پیشفرض رد میشود؛ پارامتر سوم earlier یا later انتخاب صریح میدهد. ورودی instant رشتهای باید offset یا Z داشته باشد. محاسبه تقویم و منطقه زمانی به Intl/ICU محیط متکی است.
|
|
200
|
+
|
|
201
|
+
## وضعیت بررسی
|
|
202
|
+
|
|
203
|
+
گزارش واقعی در `docs/VALIDATION.md` است. build، typecheck، تست هسته و رابط و نصب فایل خروجی بررسی شدهاند. Chromium روی دسکتاپ و نمای شبیهسازیشده موبایل بررسی شده است؛ Safari/iPhone واقعی و مرورگرهای دیگر هنوز تأیید نشدهاند. قبل از انتشار عملیاتی، موارد باقیمانده `docs/RELEASE-CHECKLIST.md` را بررسی کنید.
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
## امکانات تکمیلی ۰.۳.۰
|
|
207
|
+
|
|
208
|
+
راهنمای کامل ۲۹ Callback و ترتیب آنها: [docs/EVENTS.fa.md](docs/EVENTS.fa.md).
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
<VjnDatePicker
|
|
212
|
+
disabled={isDisabled}
|
|
213
|
+
readOnly={isReadOnly}
|
|
214
|
+
showWeekNumbers
|
|
215
|
+
showOutsideDays={false}
|
|
216
|
+
fixedWeekCount={false}
|
|
217
|
+
referenceDate="2026-10-05"
|
|
218
|
+
field={{ editable: true, commitOn: 'enter', autoFocus: true, openOn: 'icon' }}
|
|
219
|
+
/>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
فعالکردن مجدد با `disabled={false}` انجام میشود. prop جداگانه enabled وجود ندارد. readOnly امکان ویرایش را میبندد ولی مقدار همچنان در فرم ارسال میشود؛ disabled آن را از FormData کنار میگذارد. این دو وضعیت در حین بازبودن پنجره نیز تست شدهاند.
|
|
223
|
+
|
|
224
|
+
- `showWeekNumbers`: شماره هفته ISO بر اساس تاریخ ابتدای هر ردیف، مستقل از تقویم شمسی؛ برای قواعد سازمانی از `getWeekNumber` استفاده کنید.
|
|
225
|
+
- `fixedWeekCount: false`: تعداد ردیفهای موردنیاز ماه؛ پیشفرض شش ردیف است.
|
|
226
|
+
- `showOutsideDays: false`: روزهای ماه قبل/بعد را نمایش نمیدهد، ولی ساختار قابلدسترسی شبکه حفظ میشود.
|
|
227
|
+
- `referenceDate` و `defaultDisplayMonth`: مرجع تقویم خالی و ماه اولیه. `displayMonth` کنترلشده است و با `onMonthChange` به state والد وصل میشود.
|
|
228
|
+
- `view/defaultView`: نمای day/month/year. در حالت کنترلشده تغییر را با `onViewChange` اعمال کنید.
|
|
229
|
+
- `rangePosition`: مرحله کنترلشده start/end، همراه `onRangePositionChange`.
|
|
230
|
+
- `disabledDates`: فهرست ISO روزهای ممنوع. `enabledDates`: فهرست مجاز؛ آرایه خالی همه روزها را میبندد. سایر محدودیتها همچنان اعمال میشوند.
|
|
231
|
+
- `shouldDisableTime(time, date)`: محدودیت ساعت دلخواه؛ در تاریخوساعت، تاریخ انتخابی نیز داده میشود.
|
|
232
|
+
- `minDateTime/maxDateTime`: حداقل/حداکثر محلی تاریخوساعت، جدا از minTime/maxTime روزانه.
|
|
233
|
+
- `timeFormat="12h"`: نمایش AM/PM یا ق.ظ/ب.ظ؛ خروجی همچنان HH:mm در قالب ۲۴ ساعته است.
|
|
234
|
+
- `formatInput/parseInput`: قالبدهی و parser سفارشی تایپشده؛ اعتبارسنجی هسته پس از parser همچنان اجرا میشود.
|
|
235
|
+
- `validationMode`: پیشفرض `onBlur` است؛ فیلد required جدید تا خروج واقعی فوکوس قرمز نمیشود. مقدار `immediate` رفتار فوری نسخههای قبل را برمیگرداند. prop صریح `error` همیشه فوری است و `ref.validate()` مستقل از touched نتیجهٔ واقعی را میدهد.
|
|
236
|
+
- `field.commitOn`: enter، blur یا both. Enter هنگام IME composition مقدار را زودتر ثبت نمیکند.
|
|
237
|
+
- `renderEvent`: محتوای نمایشی رویداد داخل دکمه جزئیات روز؛ محتوای غیرتعاملی برگردانید.
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
import { getDateRangePreset } from 'vjndatepicker/core';
|
|
241
|
+
const currentMonth = getDateRangePreset('thisMonth', '2026-10-05', 'jalali');
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Presetها: today، yesterday، last7Days، last30Days، thisWeek، lastWeek، thisMonth، lastMonth، thisYear. خروجی بر اساس داده تقویم واقعی محاسبه میشود و محدودیتهای انتخاب هنگام مصرف بررسی میشوند.
|
|
245
|
+
|
|
246
|
+
برای تست مرورگر:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
npx playwright install chromium
|
|
250
|
+
npm run test:browser
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
این دستور دمو را روی پورت ۵۱۹۳ موقتاً اجرا میکند و تست مرورگر و بررسی خودکار axe را انجام میدهد. Safari، دستگاه واقعی و آزمون صفحهخوان جداگانهاند.
|
package/README.md
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
1
|
-
#
|
|
1
|
+
# vjndatepicker 0.3.14
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React + TypeScript + MUI date pickers for Vjn applications. Jalali/Gregorian calendars, Persian digits, RTL, caller-supplied fonts, canonical Gregorian date-only values, multi-month ranges, editable fields, mobile wheels/sheets, inline calendars, day events, and local date-time ranges.
|
|
4
|
+
|
|
5
|
+
Full Persian API guide and examples: [README.fa.md](README.fa.md).
|
|
6
|
+
|
|
7
|
+
All pickers share polished footer actions with a fixed 12px radius that stays balanced even under an oversized consumer theme. Override their layout through `slotProps.actions.sx` and text/icon button styles through `slotProps.actionButton.sx` (use explicit CSS lengths, e.g. `borderRadius: '14px'`). Composed datetime ranges now use the same default `validationMode="onBlur"`; use `"immediate"` for legacy display behavior. Validation still blocks invalid acceptance before a field is touched.
|
|
8
|
+
|
|
9
|
+
Browser and device validation instructions and actual results: [docs/VALIDATION.md](docs/VALIDATION.md).
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm ci
|
|
13
|
+
npm run dev
|
|
14
|
+
npm run check
|
|
15
|
+
npm pack --ignore-scripts
|
|
16
|
+
node scripts/consumer-smoke.mjs
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Demo: http://localhost:5173. Install the supplied tarball in a compatible application:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm install ./vjndatepicker-0.3.14.tgz
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
React, React DOM, MUI, MUI System and Emotion remain external peer dependencies. The package supports MUI 5.6 through 9 and React 18/19; compatibility is exercised against MUI 5.6, MUI 5.18 and MUI 9.4. Node >=22.12 is required for development.
|
|
26
|
+
|
|
27
|
+
The default action bar is minimal: Today and Clear are tooltip-backed icon buttons while Cancel and Accept stay textual. Use `actionDisplay="text"`, `"icon-text"`, or `"icons"` to change the presentation. Set `actionIcons={false}` to hide all action icons, or pass `actionIcons={{ today: <MyTodayIcon />, accept: false }}` to replace or hide them individually.
|
|
28
|
+
|
|
29
|
+
The desktop panel defaults to a 16px radius. Override it with `slotProps={{ panel: { sx: { borderRadius: 1 } } }}`; numeric MUI radii use the consumer theme scale.
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { VjnDateRangePicker } from 'vjndatepicker';
|
|
33
|
+
|
|
34
|
+
<VjnDateRangePicker
|
|
35
|
+
calendar="jalali"
|
|
36
|
+
locale="fa"
|
|
37
|
+
value={range}
|
|
38
|
+
onChange={setRange}
|
|
39
|
+
fieldLayout="split"
|
|
40
|
+
calendars={{ xs: 1, md: 2, xl: 3 }}
|
|
41
|
+
field={{ editable: true, openOn: 'icon' }}
|
|
42
|
+
mobile={{ months: 3, rangeLayout: 'vertical-scroll', stickyActions: true }}
|
|
43
|
+
events={events}
|
|
44
|
+
onVisibleRangeChange={loadVisibleEvents}
|
|
45
|
+
/>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Desktop fields default to editable/icon opening; mobile fields default to picker-only/both opening. Text commits on Enter or field blur. Calendar drafts commit on Apply or enabled desktop auto-accept. onChange fires only for a changed stored value; range mode then emits onRangeChange with the identical value/context before onAccept and onClose. Cancel never saves a draft. An end before the start restarts the range by default; use `rangeEndBehavior="swap"` for legacy endpoint swapping. Events are supplied by the host; badges show day details independently from date selection.
|
|
49
|
+
|
|
50
|
+
Mobile pickers default to wheels: year-only renders one focused year wheel without a redundant view switch, month-only one month wheel, year-month exactly two wheels, and a full date three wheels. Set `mobileMode="calendar"` explicitly on a picker or provider to start in calendar view. Year grids retain ascending left-to-right numeric order in both RTL and LTR layouts.
|
|
51
|
+
|
|
52
|
+
Required fields use `validationMode="onBlur"` by default, so a new untouched field is not rendered red. Use `validationMode="immediate"` for the previous behavior. An explicit `error` prop is always immediate, while `ref.validate()` always returns the actual validation result regardless of visual touched state.
|
|
53
|
+
|
|
54
|
+
VjnCalendar accepts a mode and the corresponding value model without an input or dialog. VjnDateTimeRangePicker composes one date range and two time controls and commits the whole local range explicitly. IANA conversion helpers dateTimeToInstant and instantToDateTime live in vjndatepicker/core; DST gaps are rejected and ambiguous times require a policy.
|
|
55
|
+
|
|
56
|
+
There are no bundled fonts, remote requests, official holidays, or automatic event recurrence. Multimonth mobile windows are finite; navigation advances them. See docs/VALIDATION.md for executed checks and the remaining real-browser/device checks.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
Version 0.3 adds 29 lifecycle/interaction callbacks, dynamic disabled/readOnly handling, native form reset, controlled calendar view/month, week numbers, date allow/block lists, date-specific time rules, local date-time boundaries, 12-hour clock presentation, custom parsing/formatting and real Chromium smoke tests. Full callback contracts: docs/EVENTS.fa.md.
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
npx playwright install chromium
|
|
63
|
+
npm run test:browser
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Chromium desktop and mobile emulation are tested; real Safari/iPhone and assistive-technology checks remain separate.
|