Chandra

 view release on metacpan or  search on metacpan

Chandra.xs  view on Meta::CPAN

"el.style.cssText='pointer-events:auto;display:flex;align-items:center;gap:10px;padding:12px 16px;border-radius:var(--chandra-radius,6px);background:var(--chandra-surface,#1e1e1e);color:var(--chandra-text,#e0e0e0);box-shadow:var(--chandra-shadow,0 2p...
"var ic=document.createElement('span');"
"ic.style.cssText='font-size:1.2em;flex-shrink:0;';"
"ic.textContent=o.icon;el.appendChild(ic);"
"var bd=document.createElement('div');"
"bd.style.cssText='flex:1;min-width:0;';"
"bd.textContent=msg;el.appendChild(bd);"
"if(act&&act.label){"
"var btn=document.createElement('button');"
"btn.textContent=act.label;"
"btn.style.cssText='padding:4px 12px;border:1px solid var(--chandra-border,#333);border-radius:var(--chandra-radius,4px);background:transparent;color:var(--chandra-primary,#64B5F6);cursor:pointer;font-size:0.85em;flex-shrink:0;';"
"btn.onclick=function(e){e.stopPropagation();if(act.handler)window.chandra.invoke(act.handler,[]);dismiss(id);};"
"el.appendChild(btn);}"
"var cl=document.createElement('span');"
"cl.textContent='\\u00D7';"
"cl.style.cssText='cursor:pointer;opacity:0.5;font-size:1.2em;flex-shrink:0;padding:0 2px;';"
"cl.onclick=function(e){e.stopPropagation();dismiss(id);};"
"el.appendChild(cl);"
"el.onclick=function(){dismiss(id);};"
"while(c.children.length>=5){var ol=c.firstChild;if(ol)dismiss(ol.id);}"
"c.appendChild(el);t[id]=el;"

examples/assets_mount_example.pl  view on Meta::CPAN

#!/usr/bin/env perl
#
# Example: Serving assets via protocol mount
#
# Demonstrates mounting an assets directory so that CSS, JS, and images
# are served via a custom protocol (e.g. app://css/style.css).
# The mount() call registers a protocol handler, and the injected JS
# transparently intercepts <link>, <script>, <img>, and fetch() calls.
#

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../blib/lib", "$FindBin::Bin/../blib/arch";
use File::Path qw(mkpath rmtree);
use Chandra::App;

# ---- Setup: create a sample assets directory ----

examples/assets_mount_example.pl  view on Meta::CPAN

my $app = Chandra::App->new(
    title  => 'Assets Mount Example',
    width  => 500,
    height => 400,
    debug  => 1,
);

# ---- Mount assets ----
# This registers a custom protocol handler so the webview can load
# files from $asset_dir using the "app" scheme: app://css/style.css
# The injected JS transparently intercepts <link>, <script>, <img>,
# fetch(), and <a> clicks for the "app://" scheme.

my $assets = $app->assets($asset_dir, prefix => 'app');
$assets->mount($app);

# ---- Bind a Perl function ----

$app->bind('greet', sub {
    my ($name) = @_;
    return "Hello, $name! Greetings from Perl.";

examples/canvas_demo.pl  view on Meta::CPAN

    button.demo {
        background: #27ae60;
    }
    button.demo:hover {
        background: #219a52;
    }
    .color-btn {
        width: 28px;
        height: 28px;
        border-radius: 50%;
        border: 2px solid transparent;
        cursor: pointer;
        transition: all 0.2s;
    }
    .color-btn:hover {
        transform: scale(1.1);
    }
    .color-btn.active {
        border-color: #fff;
        box-shadow: 0 0 10px rgba(255,255,255,0.5);
    }

examples/multiwindow_example.pl  view on Meta::CPAN

  .btn-add { background:#e74c3c; color:#fff; }
  .btn-settings { background:$btn_bg; color:$btn_fg; margin-left:auto; }
  .filters { display:flex; gap:4px; }
  .filters button { background:$btn_bg; color:$btn_fg; }
  .filters button.active { background:#3498db; color:#fff; }
  ul   { list-style:none; margin:0; padding:0 20px; }
  li   { display:flex; align-items:center; gap:8px; padding:10px 0;
         border-bottom:1px solid $li_border; }
  li input[type=checkbox] { width:18px; height:18px; cursor:pointer; }
  li span { flex:1; }
  li button { background:transparent; color:$del_btn; font-size:1.1em; padding:2px 6px; }
  li button:hover { color:#e74c3c; }
  .footer { padding:12px 20px; color:$footer_fg; font-size:.85em; }
</style>
</head>
<body>
<h1>Todos</h1>
<div class="toolbar">
  <button class="btn-add"
    onclick="window.chandra.invoke('open_add', [])">+ Add Todo</button>
  <div class="filters">

include/chandra/chandra_splash.h  view on Meta::CPAN

    "<div class='splash-track'>" \
    "<div class='splash-bar' id='chandra-splash-bar'></div>" \
    "</div></div></body></html>"

/* Image-only template — base64 src filled in at runtime */
#define CHANDRA_SPLASH_IMAGE_TMPL \
    "<!DOCTYPE html><html><head><meta charset='utf-8'>" \
    "<style>" \
    "* { margin: 0; padding: 0; }" \
    "body { display: flex; align-items: center; justify-content: center;" \
    "       height: 100vh; background: transparent; overflow: hidden; }" \
    "img { max-width: 100%%; max-height: 100%%; object-fit: contain; }" \
    "</style></head><body><img src='data:%s;base64,%s'></body></html>"

/* JS snippets for live updates — use textContent (safe) not innerHTML */
#define CHANDRA_SPLASH_JS_STATUS \
    "var el=document.getElementById('chandra-splash-status');" \
    "if(el)el.textContent=%s;"

#define CHANDRA_SPLASH_JS_PROGRESS \
    "var el=document.getElementById('chandra-splash-bar');" \

lib/Chandra/Assets.pm  view on Meta::CPAN

=head2 prefix

Returns the URL prefix (scheme name).

=head2 mount

    $assets->mount($app);

Register the asset protocol with a Chandra app. After mounting,
C<< prefix://path >> URLs in the webview will serve files from the
root directory.  The injected JavaScript transparently intercepts
C<< <link> >>, C<< <script> >>, C<< <img> >>, and C<fetch()> calls
for the registered scheme.

Use C<data-href> / C<data-src> attributes instead of plain C<href> /
C<src> to prevent the browser's native loader from logging a
C<"Failed to load resource: unsupported URL"> warning:

    <link rel="stylesheet" data-href="app://css/style.css">
    <script data-src="app://js/main.js"></script>
    <img data-src="app://images/logo.png">

lib/Chandra/Protocol.pm  view on Meta::CPAN


Chandra::Protocol enables custom URL scheme handling in Chandra
applications.  When a user clicks a link with a registered scheme
(e.g. C<myapp://path?key=val>), the click is intercepted and the
registered Perl handler is called with the path and parsed query
parameters.

Handlers can also be invoked programmatically from JavaScript via
C<window.__chandraProtocol.navigate(url)>.

The injected JavaScript also transparently intercepts C<< <link> >>,
C<< <script> >>, C<< <img> >>, and C<fetch()> calls whose URLs match
a registered scheme.  For C<< <link> >> and C<< <script> >> elements
the content is fetched via the Perl handler and injected inline; for
C<< <img> >> elements the data is base64-encoded into a data URI.
A C<MutationObserver> watches for dynamically added elements as well.

To avoid C<"Failed to load resource: unsupported URL"> warnings in the
developer console, use C<data-href> / C<data-src> attributes instead of
plain C<href> / C<src>:



( run in 3.539 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )