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/Nav.pm  view on Meta::CPAN

}
.chandra-nav-sidebar .chandra-nav-link:hover { background: var(--chandra-hover, #e8e8e8); }
.chandra-nav-sidebar .chandra-nav-active .chandra-nav-link {
    background: var(--chandra-selected, #e3f2fd);
    color: var(--chandra-primary, #2196F3);
    font-weight: 600;
}
.chandra-nav-separator { border-top: 1px solid var(--chandra-border, #e0e0e0); margin: 4px 12px; }
.chandra-nav-toggle {
    width: 52px; border: none;
    background: transparent;
    font-size: 1.1em; cursor: pointer;
    color: var(--chandra-text-muted, #757575);
    flex-shrink: 0;
    text-align: center;
}
.chandra-nav-icon { font-size: 1.1em; flex-shrink: 0; width: 24px; text-align: center; }
.chandra-nav-badge {
    margin-left: auto; background: var(--chandra-primary, #2196F3);
    color: #fff; padding: 1px 8px; border-radius: 10px; font-size: 0.75em;
}

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

.chandra-nav-topbar {
    background: var(--chandra-surface, #f5f5f5);
    border-bottom: 1px solid var(--chandra-border, #e0e0e0);
    padding: 0 8px;
}
.chandra-nav-topbar .chandra-nav-list { display: flex; gap: 0; }
.chandra-nav-topbar .chandra-nav-link {
    display: flex; align-items: center; gap: 6px;
    padding: 12px 16px; color: var(--chandra-text, #212121);
    text-decoration: none; cursor: pointer;
    border-bottom: 2px solid transparent;
    transition: border-color 0.15s, color 0.15s;
}
.chandra-nav-topbar .chandra-nav-link:hover { color: var(--chandra-primary, #2196F3); }
.chandra-nav-topbar .chandra-nav-active .chandra-nav-link {
    color: var(--chandra-primary, #2196F3);
    border-bottom-color: var(--chandra-primary, #2196F3);
    font-weight: 600;
}
.chandra-nav-topbar .chandra-nav-separator { display: none; }
CSS

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>:

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

    return <<'CSS';
.chandra-tabs { font-family: inherit; }
.chandra-tabs-header {
    display: flex;
    border-bottom: 1px solid var(--chandra-border, #e0e0e0);
    gap: 0;
}
.chandra-tab {
    padding: 10px 20px;
    border: none;
    background: transparent;
    color: var(--chandra-text-muted, #757575);
    cursor: pointer;
    font-size: inherit;
    font-family: inherit;
    border-bottom: 2px solid transparent;
    transition: color 0.15s, border-color 0.15s;
    display: flex;
    align-items: center;
    gap: 6px;
}
.chandra-tab:hover { color: var(--chandra-text, #212121); }
.chandra-tab-active {
    color: var(--chandra-primary, #2196F3);
    border-bottom-color: var(--chandra-primary, #2196F3);
    font-weight: 600;

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

}
.chandra-btn-primary:hover { opacity: 0.9; }

.chandra-btn-danger {
    background: var(--chandra-danger);
    color: #fff;
    border-color: var(--chandra-danger);
}

.chandra-btn-secondary {
    background: transparent;
    border-color: var(--chandra-border);
}

/* ── Inputs ───────────────────────────────────────────── */

input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="search"], input[type="url"],
input[type="tel"], input[type="date"], input[type="time"],
textarea, select {
    padding: 6px 10px;

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

    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
}
.chandra-context-menu-item:hover { background: var(--chandra-hover); }

/* ── Scrollbar (webkit) ───────────────────────────────── */

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--chandra-border);
    border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover { background: var(--chandra-text-muted); }

CSS
}

1;



( run in 3.228 seconds using v1.01-cache-2.11-cpan-7fcb06a456a )