view release on metacpan or search on metacpan
"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;