laratribe / native-datepicker
A native date picker EDGE component for NativePHP Mobile v4 with compact (calendar) and wheel modes (SwiftUI + Jetpack Compose).
Package info
github.com/laratribe/native-php-datepicker
Type:nativephp-plugin
pkg:composer/laratribe/native-datepicker
Requires
- php: ^8.2
- nativephp/mobile: ^4.0
- nativephp/mobile-ui: ^0.8
Requires (Dev)
- pestphp/pest: ^2.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-29 15:19:17 UTC
README
A native date picker EDGE component for NativePHP Mobile v4. It renders real, high-performance native OS controls on both iOS and Androidβnot a web view or HTML input.
π Highlights
- 100% Native UI:
- iOS: Rendered using SwiftUI
DatePicker(.graphical)andPicker(.wheel). - Android: Rendered using Jetpack Compose Material 3
DatePickerand snapping drum wheels.
- iOS: Rendered using SwiftUI
- Two Display Modes (
mode):compact(default): Month calendar grid for quick date browsing.wheel: Smooth day / month / year drum wheels with haptic snapping.
- Two Presentation Styles (
presentation):field(default): An interactive trigger input that opens a native sheet (iOS) or modal dialog (Android).inline: Embedded directly within your screen layout.
- Two-Way Data Binding: Seamless integration with
native:modelandnative:model.live. - Date Constraints: Set
min-dateandmax-datedown to the exact day (e.g.,max-date="today"), with automatic year-range clamping. - Timezone-Aware "Today": Guarantees that "today" resolves accurately across client and server clocks.
- Internationalization: Localize month names via BCP-47 locale tags (
en,fr-FR,ja, etc.) while keeping consistent PHP data formats. - Theme & Design Tokens: Automatically inherits NativePHP light/dark UI tokens or accepts custom hex color overrides.
- Built-in Accessibility: Native screen reader (
VoiceOverandTalkBack) labels and hints.
Why
<native:laratribe-date-picker>?
nativephp/mobile-uialready claims the defaultdate_pickerelement. This package uses thelaratribe_date_pickerelement type and<native:laratribe-date-picker>Blade tag to avoid namespace conflicts.
π Requirements
| Dependency | Minimum Version |
|---|---|
| PHP | ^8.2 |
| NativePHP Mobile | ^4.0 |
| nativephp/mobile-ui | ^0.8 |
| iOS | 16.0+ |
| Android | API 26+ (Android 8.0 Oreo) |
π Installation
1. Install via Composer
Install the package via Composer:
composer require laratribe/native-datepicker
Installing directly from GitHub repository:
If the package is not yet published on Packagist or you are using the repository directly, add the VCS repository to your rootcomposer.json:{ "repositories": [ { "type": "vcs", "url": "https://github.com/laratribe/native-php-datepicker.git" } ] }Then run:
composer require laratribe/native-datepicker:dev-main
2. Register Plugin & Publish Assets
Register the plugin in your NativePHP application:
# Publish plugin configuration (optional) php artisan vendor:publish --tag=date-picker-config # Ensure plugins provider is published php artisan vendor:publish --tag=nativephp-plugins-provider # Register and validate the plugin php artisan native:plugin:register laratribe/native-datepicker php artisan native:plugin:validate php artisan native:plugin:list
3. Build & Run the Native App
Because this plugin contains native Kotlin and Swift code, you must rebuild the application:
# Run on iOS simulator or device php artisan native:run ios # Or run on Android emulator or device php artisan native:run android
Note on Hot Reloading:
PHP and Blade changes will hot-reload instantly. However, changes to native renderer source code, the manifest, or plugin registration require re-runningnative:run(orphp artisan native:install --force).
βοΈ Configuration
Publish the config file to customize package defaults:
php artisan vendor:publish --tag=date-picker-config
This creates config/date-picker.php:
return [ /* | Default mode: 'compact' (calendar grid) or 'wheel' (day/month/year drum). | Default presentation: 'field' (input + sheet/dialog) or 'inline'. */ 'mode' => 'compact', 'presentation' => 'field', 'year_start' => 1990, 'year_end' => null, // Defaults to current year + 20 'format' => 'Y-m-d', /* | Leave keys null to inherit Native UI light/dark tokens. | Specify hex colors to override. */ 'theme' => [ 'bg' => null, 'card' => null, 'border' => null, 'text' => null, 'muted' => null, 'muted_2' => null, 'accent' => null, ], /* | Sizing options for wheel mode (density-independent dp/pt). */ 'size' => [ 'row_height' => 44, 'visible_items' => 5, // Clamped to 3, 5, or 7 'wheel_height' => null, 'card_padding' => 16, 'corner_radius' => 20, 'selected_font' => 20, 'muted_font' => 15, ], ];
π‘ Usage
Basic Example
Bind the date picker directly to a property in your NativeComponent:
namespace App\Native\Screens; use Native\Mobile\Edge\NativeComponent; class ProfileScreen extends NativeComponent { public string $birthday = '2000-01-15'; public function render() { return view('native.profile'); } }
In your Blade view (resources/views/native/profile.blade.php):
<native:laratribe-date-picker native:model="birthday" label="Birth Date" title="Select your birthday" format="Y-m-d" mode="compact" presentation="field" confirm-label="Confirm" a11y-label="Select your birthday" />
π In-Depth Examples
1. Modes & Presentations
You can mix and match mode and presentation:
{{-- 1. Calendar inside a modal dialog / bottom sheet (Default) --}} <native:laratribe-date-picker native:model="appointmentDate" mode="compact" presentation="field" label="Appointment Date" /> {{-- 2. Drum wheels drawn inline with a footer (Today / Cancel / Done) --}} <native:laratribe-date-picker native:model="birthday" mode="wheel" presentation="inline" :visible-items="5" /> {{-- 3. Drum wheels opened via a trigger field --}} <native:laratribe-date-picker native:model="deliveryDate" mode="wheel" presentation="field" placeholder="Choose Delivery Date" />
2. Constraining Dates (min-date & max-date)
Bound selectable dates down to the exact day. Useful for age verification or disabling past/future dates:
{{-- Age restriction: Must be at least 18 years old and not in the future --}} <native:laratribe-date-picker native:model="birthDate" label="Birthday" :max-date="now()->subYears(18)->toDateString()" year-start="1940" /> {{-- Booking: Only future dates within the next 30 days --}} <native:laratribe-date-picker native:model="checkIn" min-date="today" :max-date="now()->addDays(30)->toDateString()" timezone="America/New_York" />
Automatic Clamping: When
min-dateormax-dateare supplied,year-startandyear-endare automatically adjusted so that the user cannot scroll the year wheel outside the valid day range.
3. Date Formats & Timezones
Supported Formats
Supports PHP date() format tokens (Y, m, d) with common separators (-, /, ., or space), as well as standard aliases:
Y-m-dorYYYY-MM-DD(e.g.2026-07-16)d-m-YorDD-MM-YYYY(e.g.16-07-2026)m/d/YorMM/DD/YYYY(e.g.07/16/2026)d.m.YorDD.MM.YYYY(e.g.16.07.2026)
<native:laratribe-date-picker native:model="bookingDate" format="d/m/Y" />
Strict Validation: Unrecognized format tokens (like
j,n,y) will immediately throw anInvalidArgumentExceptionin PHP to avoid silent parsing errors on native devices.
Timezone Handling
Pass an IANA timezone to prevent mismatch between client device time and UTC server calculations:
<native:laratribe-date-picker max-date="today" timezone="Asia/Kolkata" />
4. Localization (locale)
Localize month and weekday labels on the native picker using standard BCP-47 locale tags. The committed value sent to your PHP component always preserves the designated format:
<native:laratribe-date-picker native:model="date" locale="fr-FR" />
5. Event Handling (on-change, on-done, on-cancel)
<native:laratribe-date-picker native:model="eventDate" on-change="handleDateChanged" on-done="handleConfirmed" on-cancel="handleCancelled" />
In your NativeComponent:
public function handleDateChanged(string $value): void { // Fires when the value changes and is confirmed } public function handleConfirmed(string $value): void { // Fires whenever Done is tapped, even if the user re-selected the current value } public function handleCancelled(): void { // Fires when the sheet/dialog is dismissed or Cancel is tapped }
Why use
on-done?
If a user opens the picker, navigates around, and selects the same date they started with,native:modelandon-changewill not fire because the value did not change (oldValue === newValue). Useon-doneif you need custom logic to execute every time the user taps Done.
6. Custom Colors & Sizing
You can override colors and sizing either via config or inline per tag:
<native:laratribe-date-picker mode="wheel" :row-height="48" :visible-items="5" :card-padding="20" :corner-radius="16" :colors="[ 'card' => '#FFFFFF', 'border' => '#E5E7EB', 'text' => '#111827', 'accent' => '#3B82F6', ]" />
visible-items: Clamped to 3, 5, or 7 to preserve vertical centering and optical balance.- Theme keys:
bg,card,border,text,muted,muted_2, andaccent.
π Attributes Reference
| Attribute | Type | Default | Description |
|---|---|---|---|
native:model |
string |
null |
Two-way data binding property name in your NativeComponent. |
value |
string |
'' |
Initial date value (if not using native:model). |
mode |
string |
'compact' |
Display style: 'compact' (month calendar grid) or 'wheel' (drum picker). |
presentation |
string |
'field' |
Presentation mode: 'field' (trigger field + dialog/sheet) or 'inline'. |
label |
string |
'' |
Floating label text above the field. |
title |
string |
'Select date' |
Header title shown in the dialog/sheet. |
placeholder |
string |
format |
Placeholder text when no date is selected. |
format |
string |
'Y-m-d' |
PHP date pattern (Y, m, d tokens only) or aliases (YYYY-MM-DD, etc.). |
min-date |
string |
null |
Minimum selectable date (e.g. '2020-01-01' or 'today'). |
max-date |
string |
null |
Maximum selectable date (e.g. '2030-12-31' or 'today'). |
year-start |
int |
1990 |
Lower bound for year picker. |
year-end |
int |
current + 20 |
Upper bound for year picker. |
timezone |
string |
'UTC' |
IANA timezone used to evaluate 'today'. |
locale |
string |
Device locale | BCP-47 tag for localizing month names (e.g. 'en', 'fr-FR', 'de'). |
default-to-today |
bool |
false |
When true, commits today's date if value is unbound. Otherwise value remains empty until confirmed. |
confirm-label |
string |
'Done' |
Text for the confirmation button. |
cancel-label |
string |
'Cancel' |
Text for the cancellation button. |
show-footer |
bool |
true in inline |
Whether to show the footer with Today/Cancel/Done buttons. |
:colors |
array |
[] |
Color overrides (card, border, text, muted, accent, etc.). |
:row-height |
int |
44 |
Row height in points/density-independent pixels (wheel mode). |
:visible-items |
int |
5 |
Number of visible items (3, 5, or 7). |
:card-padding |
int |
16 |
Internal padding of the picker container. |
:corner-radius |
int |
20 |
Rounded corner radius in dp/pt. |
on-change |
string |
null |
Component method to call when date changes upon confirmation. |
on-done |
string |
null |
Component method to call unconditionally when Done is tapped. |
on-cancel |
string |
null |
Component method to call when dismissed or cancelled. |
a11y-label |
string |
label |
Screen reader accessibility label (VoiceOver / TalkBack). |
a11y-hint |
string |
null |
Screen reader accessibility hint. |
π§ͺ Testing
Write tests for your screens using Native::test():
use Native\Mobile\Testing\Native; use App\Native\Screens\ProfileScreen; it('renders date picker with correct value', function () { Native::test(ProfileScreen::class) ->assertElement('laratribe_date_picker', function ($node) { return $node['props']['value'] === '2000-01-15' && $node['props']['mode'] === 'compact'; }); });
To run unit tests inside this package:
composer test
β FAQ & Troubleshooting
1. Why do .lazy, .debounce, or .blur throw an error?
Date pickers in NativePHP commit their state when the user taps Done. Modifiers like native:model.blur or native:model.debounce do not apply and will throw an InvalidArgumentException rather than failing silently. Use plain native:model or native:model.live.
2. Can I use this in React or Vue?
No. This plugin is built as an EDGE native component for NativePHP Mobile screens. It contains no web view or JavaScript bridge API.
3. Why is my selected date empty when the form loads?
By default, if no initial value is bound to native:model, the wire value is left as empty string ('') so your application can distinguish between "user made no selection" and a real date. To automatically commit today's date when unbound, add default-to-today="true".
π€ Author
Vishal Tiwadi
- GitHub: @Vishal09Software
- Email: vishaltiwadi09@gmail.com
If you find this package useful, please give it a βοΈ on GitHub!
π License
The MIT License (MIT). Please see License File for more information.