Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,6 @@ This project has domain-specific skills available in `**/skills/**`. You MUST ac

- Laravel can be deployed using [Laravel Cloud](https://cloud.laravel.com/), which is the fastest way to deploy and scale production Laravel applications.

=== herd rules ===

# Laravel Herd

- The application is served by Laravel Herd at `https?://[kebab-case-project-dir].test`. Use the `get-absolute-url` tool to generate valid URLs. Never run commands to serve the site. It is always available.
- Use the `herd` CLI to manage services, PHP versions, and sites (e.g. `herd sites`, `herd services:start <service>`, `herd php:list`). Run `herd list` to discover all available commands.

=== tests rules ===

# Test Enforcement
Expand Down
7 changes: 0 additions & 7 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,6 @@ This project has domain-specific skills available in `**/skills/**`. You MUST ac

- Laravel can be deployed using [Laravel Cloud](https://cloud.laravel.com/), which is the fastest way to deploy and scale production Laravel applications.

=== herd rules ===

# Laravel Herd

- The application is served by Laravel Herd at `https?://[kebab-case-project-dir].test`. Use the `get-absolute-url` tool to generate valid URLs. Never run commands to serve the site. It is always available.
- Use the `herd` CLI to manage services, PHP versions, and sites (e.g. `herd sites`, `herd services:start <service>`, `herd php:list`). Run `herd list` to discover all available commands.

=== tests rules ===

# Test Enforcement
Expand Down
55 changes: 54 additions & 1 deletion app/NativeComponents/Counter.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace App\NativeComponents;

use Illuminate\View\View;
use Native\Mobile\Attributes\Poll;
use Native\Mobile\Edge\Layouts\Builders\NavBarOptions;
use Native\Mobile\Edge\NativeComponent;
use Native\Mobile\Edge\Transition;
use Native\Mobile\Facades\Camera;

class Counter extends NativeComponent
Expand All @@ -14,6 +14,12 @@ class Counter extends NativeComponent

public $photo = '';

/** Direction of an active press-and-hold: 'up', 'down', or null. */
public ?string $holding = null;

/** Ticks elapsed in the current hold — drives step acceleration. */
public int $holdTicks = 0;

public function navTitle(): string
{
return 'Counter';
Expand All @@ -29,6 +35,53 @@ public function decrement()
$this->count--;
}

/**
* `@pressDown` — steps once immediately (so a plain tap counts), then
* arms the poll-driven repeat below for as long as the press is held.
*/
public function startHold(string $direction): void
{
$this->holding = $direction === 'down' ? 'down' : 'up';
$this->holdTicks = 0;
$this->step();
}

/** `@pressUp` — fires on release or cancel; disarms the repeat. */
public function stopHold(): void
{
$this->holding = null;
$this->holdTicks = 0;
}

/**
* Repeat engine. The poll wakes every tick regardless of hold state,
* but idle ticks re-render an identical tree, which the shadow compare
* drops before it reaches the wire — only held ticks cost anything.
* The tick cap auto-releases a hold whose pressUp never arrived.
*/
#[Poll(110)]
public function holdTick(): void
{
if ($this->holding === null) {
return;
}

if (++$this->holdTicks > 130) {
$this->stopHold();

return;
}

$this->step();
}

/** Accelerates the longer the hold: ±1, then ±2, then ±5 per tick. */
protected function step(): void
{
$delta = $this->holdTicks > 25 ? 5 : ($this->holdTicks > 8 ? 2 : 1);
$this->count += $this->holding === 'down' ? -$delta : $delta;
}

public function testCamera()
{
Camera::getPhoto()->photoTaken(function ($photo) {
Expand Down
6 changes: 4 additions & 2 deletions app/NativeComponents/DemoLauncher.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ class DemoLauncher extends NativeComponent
['id' => 'mail', 'title' => 'Mail Inbox', 'subtitle' => 'Pull-to-refresh + leading/trailing swipe actions', 'icon' => 'envelope.fill', 'color' => '#0EA5E9', 'url' => '/mail-demo'],
['id' => 'refresh', 'title' => 'Pull to refresh', 'subtitle' => 'Native pull-to-refresh on custom card content', 'icon' => 'arrow.clockwise', 'color' => '#10B981', 'url' => '/refreshable-demo'],
['id' => 'reactivity', 'title' => 'Reactivity', 'subtitle' => '#[Computed], #[Poll] and #[Lazy] placeholder in one screen', 'icon' => 'bolt.fill', 'color' => '#8B5CF6', 'url' => '/reactivity'],
['id' => 'webview', 'title' => 'Webview', 'subtitle' => 'Embedded web content — remote URL + inline HTML, @navigated events', 'icon' => 'globe', 'color' => '#3B82F6', 'url' => '/webview-demo'],
// ['id' => 'eventchannel', 'title' => 'Event Channel Test', 'subtitle' => 'Native → PHP payload > 4KB (growable event buffer)', 'icon' => 'arrow.up.arrow.down', 'color' => '#EF4444', 'url' => '/event-channel-test'],
// ['id' => 'vibe', 'title' => 'Vibe — Live Events', 'subtitle' => 'Websocket broadcast events (Vask/Reverb) into a component', 'icon' => 'antenna.radiowaves.left.and.right', 'color' => '#22C55E', 'url' => '/vibe'],
// ['id' => 'vibe-private', 'title' => 'Vibe — Private Channel', 'subtitle' => 'Authenticated private-channel subscription (bearer + /broadcasting/auth)', 'icon' => 'lock.fill', 'color' => '#16A34A', 'url' => '/vibe-private'],
// ['id' => 'vibe-presence', 'title' => 'Vibe — Presence', 'subtitle' => 'Who\'s online + live join/leave (here/joining/leaving)', 'icon' => 'person.2.fill', 'color' => '#15803D', 'url' => '/vibe-presence'],
// ['id' => 'geo-watch', 'title' => 'Geo — Watch Position', 'subtitle' => 'Streaming GPS fixes (watchPosition/clearWatch)', 'icon' => 'location.fill', 'color' => '#F97316', 'url' => '/geo-watch'],
// ['id' => 'geo-watch', 'title' => 'Geo — Watch Position', 'subtitle' => 'Streaming GPS fixes (watchPosition/clearWatch)', 'icon' => 'location.fill', 'color' => '#F97316', 'url' => '/geo-watch'],
],
],
[
Expand All @@ -57,7 +58,8 @@ class DemoLauncher extends NativeComponent
['id' => 'gestures', 'title' => 'Gestures', 'subtitle' => 'Double-tap (@doubleTap) ', 'icon' => 'hand.tap.fill', 'color' => '#6366F1', 'url' => '/gestures'],
['id' => 'transitions', 'title' => 'Page Transitions', 'subtitle' => 'Fade, slide, scale - every @navigate animation', 'icon' => 'arrow.left.arrow.right', 'color' => '#14B8A6', 'url' => '/transitions'],
['id' => 'animate', 'title' => 'Animations', 'subtitle' => 'Awesome native animations', 'icon' => 'sparkles', 'color' => '#F59E0B', 'url' => '/animate'],
// ['id' => 'glass', 'title' => 'Glass', 'subtitle' => 'Liquid Glass Demo', 'icon' => 'drop.fill', 'color' => '#0EA5E9', 'url' => '/glass'],
['id' => 'numberswitcher', 'title' => 'Number Switcher', 'subtitle' => 'content-transition — rolling in-place digit changes', 'icon' => 'textformat.123', 'color' => '#14B8A6', 'url' => '/number-switcher'],
// ['id' => 'glass', 'title' => 'Glass', 'subtitle' => 'Liquid Glass Demo', 'icon' => 'drop.fill', 'color' => '#0EA5E9', 'url' => '/glass'],
['id' => 'nativetabs', 'title' => 'Native Tabs', 'subtitle' => 'TabView-rendered bottom bar; Liquid Glass on iOS 26+', 'icon' => 'rectangle.split.3x1', 'color' => '#A855F7', 'url' => '/native-tabs'],
['id' => 'drawer', 'title' => 'Side Drawer', 'subtitle' => 'X-style slide-out nav — modal + reveal, declared once on the layout', 'icon' => 'line.3.horizontal', 'color' => '#6366F1', 'url' => '/drawer'],
['id' => 'syncupnative', 'title' => 'SyncUp Messaging', 'subtitle' => 'Login, chat threads, friends, profile (5 screens) — custom chrome', 'icon' => 'bubble.left.fill', 'color' => '#0891b2', 'url' => '/syncup-native'],
Expand Down
4 changes: 2 additions & 2 deletions app/NativeComponents/Layouts/DrawerLayout.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

use Native\Mobile\Edge\Layouts\NativeLayout;
use Native\Mobile\Edge\NativeComponent;
use Nativephp\NativeUi\Builders\Drawer;
use Nativephp\NativeUi\Concerns\HasLayoutDrawer;
use Native\Mobile\UI\Builders\Drawer;
use Native\Mobile\UI\Concerns\HasLayoutDrawer;

/**
* Demo layout for the content-agnostic side drawer (X-style side nav).
Expand Down
48 changes: 48 additions & 0 deletions app/NativeComponents/NumberSwitcherDemo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace App\NativeComponents;

use Illuminate\View\View;
use Native\Mobile\Edge\NativeComponent;

/**
* Showcase for `content-transition` on <native:text> — the "number
* switcher": digits roll in place as the value changes (SwiftUI
* numericText on iOS, directional slide + fade on Android) instead of
* swapping cold. The side-by-side row renders the same value through
* each mode so the difference is visible at a glance.
*/
class NumberSwitcherDemo extends NativeComponent
{
public int $value = 1024;

public function increment(): void
{
$this->value++;
}

public function decrement(): void
{
$this->value = max(0, $this->value - 1);
}

public function jump(): void
{
$this->value += 111;
}

public function randomize(): void
{
$this->value = random_int(0, 99999);
}

public function navTitle(): string
{
return 'Number Switcher';
}

public function render(): View
{
return view('native.number-switcher');
}
}
2 changes: 1 addition & 1 deletion app/NativeComponents/Phase4VirtualListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use Native\Mobile\Edge\Layouts\Builders\NavBarOptions;
use Native\Mobile\Edge\NativeComponent;
use Native\Mobile\Edge\Traits\HasVirtualListWindow;
use Nativephp\NativeUi\Elements\NativeVirtualList;
use Native\Mobile\UI\Elements\NativeVirtualList;

/**
* Phase 4 — list virtualization verification screen.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
use Native\Mobile\Edge\Layouts\Builders\TabBar;
use Native\Mobile\Edge\Layouts\NativeLayout;
use Native\Mobile\Edge\NativeComponent;
use Nativephp\NativeUi\Builders\FloatingOverlay;
use Nativephp\NativeUi\Concerns\HasFloatingOverlay;

/**
* Native-chrome variant of SyncUp's tabs layout. Same shape as the
Expand Down
78 changes: 78 additions & 0 deletions app/NativeComponents/WebviewDemo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace App\NativeComponents;

use Illuminate\View\View;
use Native\Mobile\Edge\NativeComponent;

class WebviewDemo extends NativeComponent
{
public string $url = 'https://example.com';

public string $lastNavigatedUrl = '';

public string $mode = 'remote';

public function showRemote(): void
{
$this->mode = 'remote';
}

public function showLocal(): void
{
$this->mode = 'local';
}

public function showPhp(): void
{
$this->mode = 'php';
}

public function showFullscreen(): void
{
$this->mode = 'fullscreen';
}

public function onUrlChanged(string $url): void
{
$this->lastNavigatedUrl = $url;
}

public function navTitle(): string
{
return 'Webview';
}

public function render(): View
{
return view('native.webview-demo', [
'localHtml' => $this->localHtml(),
]);
}

private function localHtml(): string
{
return <<<'HTML'
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { margin: 0; font: 16px -apple-system, system-ui, sans-serif;
padding: 24px; color: #111; background: #fef3c7; }
h1 { margin: 0 0 12px; font-size: 22px; }
p { margin: 0 0 8px; }
code { background: rgba(0,0,0,.08); padding: 2px 6px; border-radius: 4px; }
</style>
</head>
<body>
<h1>Inline HTML slot</h1>
<p>This document was loaded with <code>baseURL = null</code>, so the
webview has an opaque origin and cannot reach back into the host app.</p>
<p>JavaScript is disabled by default — try clicking this:</p>
<p><a href="https://example.org">example.org</a> (will fire <code>@navigated</code>).</p>
</body>
</html>
HTML;
}
}
9 changes: 2 additions & 7 deletions app/Providers/NativeServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Native\Mobile\Providers\CameraServiceProvider;
use Native\Mobile\Providers\DeviceServiceProvider;
use Native\Mobile\Providers\DialogServiceProvider;
use Native\Mobile\Providers\GeolocationServiceProvider;
use Native\Mobile\Providers\SecureStorageServiceProvider;
use Nativephp\NativeUi\NativeUIServiceProvider;
use Native\Mobile\UI\NativeUIServiceProvider;

class NativeServiceProvider extends ServiceProvider
{
Expand Down Expand Up @@ -40,7 +35,7 @@ public function boot(): void
public function plugins(): array
{
return [
NativeUIServiceProvider::class
NativeUIServiceProvider::class,
];
}
}
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
"php": "^8.4",
"laravel/framework": "^13.0",
"laravel/tinker": "^3.0",
"nativephp/mobile": "dev-element",
"nativephp/mobile": "dev-main as 4.0.x-dev",
"nativephp/mobile-camera": "*",
"nativephp/native-ui": "*"
"nativephp/mobile-ui": "^0.2"
},
"require-dev": {
"fakerphp/faker": "^1.23",
Expand Down
Loading
Loading