refactor(sys-bar): grouped pill theme picker + remove three orphaned components
Theme picker (e_app_sys_bar.svelte): - Replace flat <select> dropdown with grouped pill buttons - Two groups: 'System' (Skeleton defaults) and 'AE' (custom themes) - Active theme highlighted via bg-primary-500 (shows in the current theme's own primary color — instant visual confirmation) - Pill labels shortened where helpful (e.g. 'AE_Firefly_SteelBlue' → 'Steel ✦') - Rename theme_options → skeleton_themes + ae_themes; extract apply_theme() shared handler (removes duplicated setAttribute + ae_loc.update pattern) Orphaned component removal (→ ~/tmp/agents_trash): - e_app_theme.svelte — only imported by the dead legacy menu; the sys_bar Appearance section fully covers it - e_app_sys_menu_legacy.svelte — no consumers anywhere in the codebase; sys_bar (mounted in +layout.svelte) fully replaces it - e_app_cfg.svelte — only mounted from the dead legacy menu; its live functionality (iframe toggle, reload, URL builder) is all in sys_bar's Dev/Tools section npx svelte-check: 0 errors (file count drops from 5403 → 5400) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,331 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import {
|
|
||||||
Code,
|
|
||||||
Eraser,
|
|
||||||
LockOpen,
|
|
||||||
RefreshCw,
|
|
||||||
Settings,
|
|
||||||
ShieldCheck,
|
|
||||||
ShieldUser,
|
|
||||||
Trash2,
|
|
||||||
UserRound,
|
|
||||||
Users
|
|
||||||
} from '@lucide/svelte';
|
|
||||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
|
||||||
import {
|
|
||||||
ae_loc,
|
|
||||||
ae_sess,
|
|
||||||
ae_api,
|
|
||||||
slct,
|
|
||||||
slct_trigger
|
|
||||||
} from '$lib/stores/ae_stores';
|
|
||||||
import E_app_url_builder from '$lib/app_components/e_app_url_builder.svelte';
|
|
||||||
|
|
||||||
// import Element_theme from '$lib/e_app_theme.svelte';
|
|
||||||
|
|
||||||
let notes: null | string = null;
|
|
||||||
let all: boolean = false;
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
log_lvl?: number;
|
|
||||||
hide?: null | boolean;
|
|
||||||
expand?: boolean;
|
|
||||||
// export let theme_mode: null|string = null;
|
|
||||||
// set_theme_mode?: null|boolean;
|
|
||||||
// export let theme_name: null|string = null;
|
|
||||||
// set_theme_name?: null|boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
let {
|
|
||||||
log_lvl = $bindable(0),
|
|
||||||
hide = $bindable(false),
|
|
||||||
expand = $bindable(false)
|
|
||||||
// set_theme_mode = null,
|
|
||||||
// set_theme_name = null
|
|
||||||
}: Props = $props();
|
|
||||||
|
|
||||||
// const dispatch = createEventDispatcher();
|
|
||||||
|
|
||||||
// onMount(() => {
|
|
||||||
// // console.log('** Element Mounted: ** Element App Config');
|
|
||||||
// if (set_theme_mode) {
|
|
||||||
// $slct_trigger = 'set_theme_mode';
|
|
||||||
// }
|
|
||||||
// if (set_theme_name) {
|
|
||||||
// $slct_trigger = 'set_theme_name';
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// $: if ($slct_trigger == 'set_theme_mode' && $ae_loc?.app_cfg?.theme_mode) {
|
|
||||||
// console.log(`$ae_loc.app_cfg.theme_mode=${$ae_loc?.app_cfg?.theme_mode}`);
|
|
||||||
// $slct_trigger = null;
|
|
||||||
// if ($ae_loc.app_cfg.theme_mode == 'light') {
|
|
||||||
// document.documentElement.classList.remove('dark');
|
|
||||||
// document.documentElement.classList.add('light');
|
|
||||||
// } else if ($ae_loc.app_cfg.theme_mode == 'dark') {
|
|
||||||
// document.documentElement.classList.remove('light');
|
|
||||||
// document.documentElement.classList.add('dark');
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $: if ($slct_trigger == 'set_theme_name' && $ae_loc?.app_cfg?.theme_name) {
|
|
||||||
// console.log(`$ae_loc?.app_cfg?.theme_name=${$ae_loc?.app_cfg?.theme_name}`);
|
|
||||||
// $slct_trigger = null;
|
|
||||||
// // Update the body attribute named "data-theme" to the current theme name.
|
|
||||||
// document.body.setAttribute('data-theme', $ae_loc?.app_cfg?.theme_name);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $: if (entered_passcode && entered_passcode.length >= 5) {
|
|
||||||
// console.log(`entered_passcode=${entered_passcode}`);
|
|
||||||
// handle_check_access_type_passcode();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $: if (trigger && $ae_loc.access_type) {
|
|
||||||
// console.log(`$ae_loc.access_type=${$ae_loc.access_type}`);
|
|
||||||
|
|
||||||
// let access_checks_results = ae_util.process_permission_checks($ae_loc.access_type);
|
|
||||||
|
|
||||||
// $ae_loc = {...$ae_loc, ...access_checks_results};
|
|
||||||
// } else if (trigger) {
|
|
||||||
// console.log(`$ae_loc.access_type=not set`);
|
|
||||||
|
|
||||||
// // Send an empty string to reset the permissions. This is the same as sending 'anonymous'.
|
|
||||||
// let access_checks_results = ae_util.process_permission_checks('');
|
|
||||||
|
|
||||||
// $ae_loc = {...$ae_loc, ...access_checks_results};
|
|
||||||
// }
|
|
||||||
|
|
||||||
function handle_something() {
|
|
||||||
// console.log('*** handle_something() ***');
|
|
||||||
}
|
|
||||||
|
|
||||||
function handle_clear_storage(item: null | string) {
|
|
||||||
// console.log('*** handle_clear_storage() ***');
|
|
||||||
// window.localStorage.setItem('access_type', 'anonymous');
|
|
||||||
// return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// function dispatch_something_changed() {
|
|
||||||
// console.log('*** dispatch_something_changed() ***');
|
|
||||||
|
|
||||||
// console.log(ae_util);
|
|
||||||
// console.log($ae_loc);
|
|
||||||
|
|
||||||
// dispatch('access_type_changed', {
|
|
||||||
// access_type: $ae_loc.access_type
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- transition duration-500 delay-1000 hover:duration-500 hover:delay-1000 hover:transition-all -->
|
|
||||||
<section
|
|
||||||
id="AE-App-Cfg"
|
|
||||||
class="
|
|
||||||
ae_app_cfg
|
|
||||||
hidden-print
|
|
||||||
|
|
||||||
flex w-72
|
|
||||||
max-w-72 flex-col
|
|
||||||
|
|
||||||
flex-wrap items-end justify-center gap-1
|
|
||||||
border-2 border-gray-200
|
|
||||||
|
|
||||||
bg-blue-100 p-1
|
|
||||||
text-gray-900
|
|
||||||
transition-all delay-150
|
|
||||||
|
|
||||||
duration-300 hover:delay-1000 hover:ease-out dark:bg-blue-800
|
|
||||||
dark:text-gray-200
|
|
||||||
"
|
|
||||||
class:hidden={hide}>
|
|
||||||
<header class:hidden={!expand} class="ae_header w-full">
|
|
||||||
<h2 class="text-center text-sm font-semibold">Config</h2>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="ae_cfg_content my-4 space-y-4 text-xs"
|
|
||||||
class:hidden={!expand}
|
|
||||||
data-sveltekit-preload-data="false">
|
|
||||||
<section class="space-y-2">
|
|
||||||
<div>
|
|
||||||
<h2 class="strong">Access Type:</h2>
|
|
||||||
</div>
|
|
||||||
{#if $ae_loc.access_type && $ae_loc.access_type != 'anonymous'}
|
|
||||||
{#if $ae_loc.access_type == 'super'}
|
|
||||||
<ShieldCheck size="1em" class="mx-1" /> Super Access
|
|
||||||
{:else if $ae_loc.access_type == 'manager'}
|
|
||||||
<ShieldUser size="1em" class="mx-1" /> Manager Access
|
|
||||||
{:else if $ae_loc.access_type == 'administrator'}
|
|
||||||
<UserRound size="1em" class="mx-1" /> Administrator Access
|
|
||||||
{:else if $ae_loc.access_type == 'trusted'}
|
|
||||||
<UserRound size="1em" class="mx-1" /> Trusted Access
|
|
||||||
{:else if $ae_loc.access_type == 'authenticated'}
|
|
||||||
<Users size="1em" class="mx-1" /> Authenticated Access
|
|
||||||
{:else if $ae_loc.access_type == 'anonymous'}
|
|
||||||
<Users size="1em" class="mx-1" /> Anonymous Access
|
|
||||||
{:else}
|
|
||||||
<LockOpen size="1em" class="mx-1" /> Unknown Access
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- <button
|
|
||||||
class="btn btn-sm variant-glass-secondary access_type_lock_btn hover:transition-all"
|
|
||||||
title="Access mode is currently enabled/unlocked. Click to exit and lock."
|
|
||||||
>
|
|
||||||
<span class="fas fa-lock mx-1"></span> Lock
|
|
||||||
</button> -->
|
|
||||||
{:else}
|
|
||||||
Not logged in
|
|
||||||
{/if}
|
|
||||||
</section>
|
|
||||||
<!-- END: Access Type -->
|
|
||||||
|
|
||||||
<section class="space-y-2">
|
|
||||||
<h2 class="strong">Utilities:</h2>
|
|
||||||
<a class="btn btn-sm preset-tonal-secondary" href="/hosted_files">
|
|
||||||
<Code size="1em" class="mx-1" />
|
|
||||||
Util: Convert Videos
|
|
||||||
</a>
|
|
||||||
|
|
||||||
{#if $ae_loc.iframe}
|
|
||||||
<a
|
|
||||||
class="btn btn-sm preset-tonal-secondary"
|
|
||||||
href="/?iframe=false">
|
|
||||||
<Code size="1em" class="mx-1" />
|
|
||||||
Exit iframe Mode
|
|
||||||
</a>
|
|
||||||
{:else}
|
|
||||||
<a
|
|
||||||
class="btn btn-sm preset-tonal-secondary"
|
|
||||||
href="/?iframe=true">
|
|
||||||
<Code size="1em" class="mx-1" />
|
|
||||||
Use iframe Mode
|
|
||||||
</a>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
class="btn btn-sm preset-tonal-warning"
|
|
||||||
title="Reload and clear the page cache"
|
|
||||||
onclick={() => {
|
|
||||||
// $ae_loc.
|
|
||||||
window.location.reload();
|
|
||||||
}}>
|
|
||||||
<RefreshCw size="1em" class="mx-1" />
|
|
||||||
Reload &
|
|
||||||
<Trash2 size="1em" class="mx-1" />
|
|
||||||
Clear Cache
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class="btn btn-sm preset-tonal-warning"
|
|
||||||
title="Full Reset: Delete ALL IndexedDB databases, clear localStorage and sessionStorage for this origin, then reload."
|
|
||||||
onclick={async () => {
|
|
||||||
if (
|
|
||||||
!confirm(
|
|
||||||
'FULL RESET: Delete ALL IndexedDB databases, clear localStorage and sessionStorage, then reload? This cannot be undone.'
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const db_list = await indexedDB.databases();
|
|
||||||
console.log('[clear_all] IDB databases found:', db_list.map((d) => d.name));
|
|
||||||
for (const db of db_list) {
|
|
||||||
if (db.name) indexedDB.deleteDatabase(db.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.clear();
|
|
||||||
sessionStorage.clear();
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
}}>
|
|
||||||
<Eraser size="1em" class="mx-1" />
|
|
||||||
Clear Storage & DB
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<!-- END: Utilities -->
|
|
||||||
|
|
||||||
<section class="space-y-2">
|
|
||||||
<E_app_url_builder />
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- class:justify-between={expand}
|
|
||||||
class:justify-end={!expand} -->
|
|
||||||
<div class="flex w-full flex-row items-center justify-between gap-2">
|
|
||||||
<!-- {#if !expand} -->
|
|
||||||
<span>
|
|
||||||
{#if $ae_loc.access_type && $ae_loc.access_type != 'anonymous'}
|
|
||||||
{#if $ae_loc.access_type == 'super'}
|
|
||||||
<ShieldCheck size="1em" class="mx-1" /> Super Access
|
|
||||||
{:else if $ae_loc.access_type == 'manager'}
|
|
||||||
<ShieldUser size="1em" class="mx-1" /> Manager Access
|
|
||||||
{:else if $ae_loc.access_type == 'administrator'}
|
|
||||||
<UserRound size="1em" class="mx-1" /> Administrator Access
|
|
||||||
{:else if $ae_loc.access_type == 'trusted'}
|
|
||||||
<UserRound size="1em" class="mx-1" /> Trusted Access
|
|
||||||
{:else if $ae_loc.access_type == 'authenticated'}
|
|
||||||
<Users size="1em" class="mx-1" /> Authenticated Access
|
|
||||||
{:else if $ae_loc.access_type == 'anonymous'}
|
|
||||||
<Users size="1em" class="mx-1" /> Anonymous Access
|
|
||||||
{:else}
|
|
||||||
<LockOpen size="1em" class="mx-1" /> Unknown Access
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- <button
|
|
||||||
class="btn btn-sm variant-glass-secondary access_type_lock_btn hover:transition-all"
|
|
||||||
title="Access mode is currently enabled/unlocked. Click to exit and lock."
|
|
||||||
>
|
|
||||||
<span class="fas fa-lock mx-1"></span> Lock
|
|
||||||
</button> -->
|
|
||||||
{:else}
|
|
||||||
Not logged in
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
<!-- {/if} -->
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="
|
|
||||||
ae_cfg_btn
|
|
||||||
btn btn-sm preset-tonal-warning
|
|
||||||
group
|
|
||||||
text-sm transition-all
|
|
||||||
"
|
|
||||||
onclick={() => {
|
|
||||||
expand = !expand;
|
|
||||||
}}>
|
|
||||||
<!-- <span class="fas fa-cog m-1"></span> -->
|
|
||||||
<span class="inline-block" title="Settings">
|
|
||||||
<Settings class="m-1" />
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="
|
|
||||||
cfg_text
|
|
||||||
hidden
|
|
||||||
group-hover:inline
|
|
||||||
">
|
|
||||||
Settings
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<style lang="postcss">
|
|
||||||
.ae_cfg_btn .cfg_text {
|
|
||||||
/* display: none; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.ae_cfg_btn:hover .cfg_text {
|
|
||||||
/* display: initial; */
|
|
||||||
/* outline: solid thin red; */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .access_type .current_text {
|
|
||||||
display: none;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* .access_type:hover .current_text {
|
|
||||||
display: initial;
|
|
||||||
} */
|
|
||||||
/* END: AE's Svelte App Config component */
|
|
||||||
</style>
|
|
||||||
@@ -204,30 +204,39 @@ let access_label = $derived.by(() => {
|
|||||||
return map[t] ?? t;
|
return map[t] ?? t;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Theme options — keep in sync with e_app_url_builder.svelte
|
// Theme picker groups — keep label lists in sync with e_app_url_builder.svelte
|
||||||
const theme_options = [
|
// Skeleton system themes (first-party, no AE prefix)
|
||||||
{ value: '', label: '-- None --' },
|
const skeleton_themes = [
|
||||||
|
{ value: 'nouveau', label: 'Nouveau' },
|
||||||
{ value: 'cerberus', label: 'Cerberus' },
|
{ value: 'cerberus', label: 'Cerberus' },
|
||||||
{ value: 'concord', label: 'Concord' },
|
{ value: 'concord', label: 'Concord' },
|
||||||
{ value: 'crimson', label: 'Crimson' },
|
{ value: 'crimson', label: 'Crimson' },
|
||||||
{ value: 'hamlindigo', label: 'Hamlindigo' },
|
{ value: 'hamlindigo', label: 'Hamlindigo' },
|
||||||
{ value: 'modern', label: 'Modern' },
|
{ value: 'modern', label: 'Modern' },
|
||||||
{ value: 'nouveau', label: 'Nouveau' },
|
|
||||||
{ value: 'rocket', label: 'Rocket' },
|
{ value: 'rocket', label: 'Rocket' },
|
||||||
{ value: 'terminus', label: 'Terminus' },
|
{ value: 'terminus', label: 'Terminus' },
|
||||||
{ value: 'vintage', label: 'Vintage' },
|
{ value: 'vintage', label: 'Vintage' },
|
||||||
{ value: 'wintry', label: 'Wintry' },
|
{ value: 'wintry', label: 'Wintry' },
|
||||||
|
];
|
||||||
|
// AE custom themes
|
||||||
|
const ae_themes = [
|
||||||
{ value: 'AE_OSIT_default', label: 'OSIT' },
|
{ value: 'AE_OSIT_default', label: 'OSIT' },
|
||||||
{ value: 'AE_Firefly', label: 'Firefly ✦' },
|
{ value: 'AE_Firefly', label: 'Firefly ✦' },
|
||||||
{ value: 'AE_Firefly_SteelBlue', label: 'Firefly SteelBlue ✦' },
|
{ value: 'AE_Firefly_SteelBlue', label: 'Steel ✦' },
|
||||||
{ value: 'AE_Firefly_Indigo', label: 'Firefly Indigo ✦' },
|
{ value: 'AE_Firefly_Indigo', label: 'Indigo ✦' },
|
||||||
{ value: 'AE_Firefly_Rainbow', label: 'Firefly Rainbow ✨' },
|
{ value: 'AE_Firefly_Rainbow', label: 'Rainbow ✨' },
|
||||||
{ value: 'AE_Firefly_Axonius', label: 'Firefly Axonius ✦' },
|
{ value: 'AE_Firefly_Axonius', label: 'Axonius ✦' },
|
||||||
{ value: 'AE_Firefly_BGH', label: 'Firefly BGH ✦' },
|
{ value: 'AE_Firefly_BGH', label: 'BGH ✦' },
|
||||||
{ value: 'AE_c_IDAA_light', label: 'IDAA – light' },
|
{ value: 'AE_c_IDAA_light', label: 'IDAA' },
|
||||||
{ value: 'AE_c_LCI', label: 'LCI' },
|
{ value: 'AE_c_LCI', label: 'LCI' },
|
||||||
{ value: 'AE_c_LCI_new', label: 'LCI (New ✦)' }
|
{ value: 'AE_c_LCI_new', label: 'LCI New ✦' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function apply_theme(value: string) {
|
||||||
|
document.documentElement.setAttribute('data-theme', value);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
ae_loc.update((l: Record<string, any>) => ({ ...l, theme_name: value, user_theme_selected: true }));
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- ══════════════════════════════════════════════════════════════════════════
|
<!-- ══════════════════════════════════════════════════════════════════════════
|
||||||
@@ -432,25 +441,45 @@ const theme_options = [
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Theme name select -->
|
<!-- Theme picker: grouped pills -->
|
||||||
<div class="space-y-1.5">
|
<div class="space-y-2">
|
||||||
<div
|
<div class="text-xs font-medium text-gray-400 dark:text-gray-500">Theme</div>
|
||||||
class="text-xs font-medium text-gray-400 dark:text-gray-500">
|
|
||||||
Theme
|
<!-- Skeleton system themes -->
|
||||||
|
<div class="space-y-1">
|
||||||
|
<div class="text-[10px] font-semibold uppercase tracking-wider text-gray-300 dark:text-gray-600">System</div>
|
||||||
|
<div class="flex flex-wrap gap-1">
|
||||||
|
{#each skeleton_themes as opt (opt.value)}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => apply_theme(opt.value)}
|
||||||
|
class="rounded-md px-2 py-0.5 text-xs transition-all
|
||||||
|
{$ae_loc.theme_name === opt.value
|
||||||
|
? 'bg-primary-500 text-white font-semibold shadow-sm'
|
||||||
|
: 'bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600'}">
|
||||||
|
{opt.label}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- AE custom themes -->
|
||||||
|
<div class="space-y-1">
|
||||||
|
<div class="text-[10px] font-semibold uppercase tracking-wider text-gray-300 dark:text-gray-600">AE</div>
|
||||||
|
<div class="flex flex-wrap gap-1">
|
||||||
|
{#each ae_themes as opt (opt.value)}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => apply_theme(opt.value)}
|
||||||
|
class="rounded-md px-2 py-0.5 text-xs transition-all
|
||||||
|
{$ae_loc.theme_name === opt.value
|
||||||
|
? 'bg-primary-500 text-white font-semibold shadow-sm'
|
||||||
|
: 'bg-gray-100 text-gray-600 hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600'}">
|
||||||
|
{opt.label}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<select
|
|
||||||
bind:value={$ae_loc.theme_name}
|
|
||||||
onchange={(e) => {
|
|
||||||
const v = (e.target as HTMLSelectElement).value;
|
|
||||||
document.documentElement.setAttribute('data-theme', v);
|
|
||||||
ae_loc.update((l: any) => ({ ...l, theme_name: v, user_theme_selected: true }));
|
|
||||||
}}
|
|
||||||
class="select w-full border border-gray-300 bg-white text-sm text-gray-900 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100">
|
|
||||||
{#each theme_options as opt (opt.value)}
|
|
||||||
<option value={opt.value}
|
|
||||||
>{opt.label}</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,620 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
// *** Import Svelte specific
|
|
||||||
// import { tick } from 'svelte';
|
|
||||||
// import { goto, invalidateAll } from '$app/navigation';
|
|
||||||
|
|
||||||
// *** Import other supporting libraries
|
|
||||||
import {
|
|
||||||
// ArrowBigRight,
|
|
||||||
// Bug,
|
|
||||||
CircleX,
|
|
||||||
// Eye, EyeOff,
|
|
||||||
// Key,
|
|
||||||
// LogIn, LogOut, LockKeyhole,
|
|
||||||
// Mail, MailCheck,
|
|
||||||
Menu,
|
|
||||||
// RefreshCw, RefreshCcwDot,
|
|
||||||
ShieldEllipsis,
|
|
||||||
ShieldMinus,
|
|
||||||
ShieldPlus,
|
|
||||||
ShieldUser,
|
|
||||||
ToggleLeft,
|
|
||||||
ToggleRight,
|
|
||||||
User,
|
|
||||||
UserCheck,
|
|
||||||
UserCog,
|
|
||||||
Wand2,
|
|
||||||
X
|
|
||||||
} from '@lucide/svelte';
|
|
||||||
|
|
||||||
// *** Import Aether specific variables and functions
|
|
||||||
// import { ae_util } from '$lib/ae_utils/ae_utils';
|
|
||||||
import {
|
|
||||||
ae_loc,
|
|
||||||
ae_sess,
|
|
||||||
ae_api,
|
|
||||||
slct,
|
|
||||||
slct_trigger
|
|
||||||
} from '$lib/stores/ae_stores';
|
|
||||||
|
|
||||||
import Element_access_type from '$lib/app_components/e_app_access_type.svelte';
|
|
||||||
import Element_app_cfg from '$lib/app_components/e_app_cfg.svelte';
|
|
||||||
import Element_sign_in_out from '$lib/app_components/e_app_sign_in_out.svelte';
|
|
||||||
import Element_theme from '$lib/app_components/e_app_theme.svelte';
|
|
||||||
|
|
||||||
// *** Setup Svelte properties
|
|
||||||
interface Props {
|
|
||||||
log_lvl?: number;
|
|
||||||
data: any;
|
|
||||||
hide?: null | boolean;
|
|
||||||
expand?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
let {
|
|
||||||
log_lvl = $bindable(0),
|
|
||||||
data = null,
|
|
||||||
hide = $bindable(false),
|
|
||||||
expand = $bindable(false)
|
|
||||||
}: Props = $props();
|
|
||||||
|
|
||||||
let trigger_clear_access: null | boolean = $state(null);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- App System Menu -->
|
|
||||||
<!-- min-h-full
|
|
||||||
max-h-max
|
|
||||||
min-w-full
|
|
||||||
max-w-max -->
|
|
||||||
<!-- <section
|
|
||||||
class="
|
|
||||||
ae_app__menu
|
|
||||||
hidden-print
|
|
||||||
flex flex-col
|
|
||||||
items-end justify-center
|
|
||||||
gap-1
|
|
||||||
absolute right-0 bottom-16
|
|
||||||
hover:bottom-6
|
|
||||||
bg-white dark:bg-gray-800
|
|
||||||
border border-transparent
|
|
||||||
hover:border hover:border-gray-200 hover:dark:border-gray-700
|
|
||||||
rounded-lg
|
|
||||||
p-2
|
|
||||||
*:hover:inline
|
|
||||||
opacity-40
|
|
||||||
hover:opacity-100
|
|
||||||
duration-50 delay-1000 hover:delay-100 hover:ease-out
|
|
||||||
transition hover:transition-all
|
|
||||||
z-10 hover:z-20
|
|
||||||
"
|
|
||||||
class:hidden={!expand_btn}
|
|
||||||
> -->
|
|
||||||
<!-- && !expand -->
|
|
||||||
<!-- !$ae_loc
|
|
||||||
?.sys_menu?.expand_btn -->
|
|
||||||
<!-- bg-blue-100/60 dark:bg-blue-800/50 -->
|
|
||||||
<!-- class:hover:border-transparent={!expand} -->
|
|
||||||
<!-- mx-1 my-2 -->
|
|
||||||
<!-- We need to be able to hide the menu button in certain situations. Mainly iframes. -->
|
|
||||||
<section
|
|
||||||
class="
|
|
||||||
ae_app__sys_menu
|
|
||||||
|
|
||||||
hidden-print
|
|
||||||
md:text-md
|
|
||||||
lg:text-md xl:text-md absolute
|
|
||||||
|
|
||||||
right-0
|
|
||||||
bottom-6
|
|
||||||
|
|
||||||
z-50
|
|
||||||
flex
|
|
||||||
|
|
||||||
w-min max-w-md flex-col-reverse
|
|
||||||
items-end justify-center
|
|
||||||
|
|
||||||
gap-1 rounded-lg border-2 border-blue-300/20 bg-blue-200/90 text-sm
|
|
||||||
|
|
||||||
opacity-90
|
|
||||||
|
|
||||||
transition-all delay-500
|
|
||||||
duration-500 ease-in-out
|
|
||||||
hover:border-blue-500/20 hover:opacity-100
|
|
||||||
|
|
||||||
hover:delay-200
|
|
||||||
hover:duration-200 sm:text-sm
|
|
||||||
2xl:text-lg dark:border-blue-700/20
|
|
||||||
hover:dark:border-blue-500/20
|
|
||||||
"
|
|
||||||
class:top-0={expand && (1 as any) == 3}
|
|
||||||
class:opacity-100={expand}
|
|
||||||
class:w-full={expand}
|
|
||||||
class:hidden={hide}
|
|
||||||
class:border-transparent={!expand}
|
|
||||||
class:bg-transparent={!expand}>
|
|
||||||
<!-- class:hidden={!expand} -->
|
|
||||||
<!-- class:preset-filled-warning-100-900={expand} -->
|
|
||||||
<div
|
|
||||||
class:opacity-50={!expand}
|
|
||||||
class:opacity-100={expand}
|
|
||||||
class:light:bg-blue-500={expand}
|
|
||||||
class:dark:bg-blue-500={expand}
|
|
||||||
class="
|
|
||||||
hidden-print
|
|
||||||
light:bg-blue-200/10 relative flex w-full
|
|
||||||
flex-col
|
|
||||||
|
|
||||||
items-end
|
|
||||||
justify-end
|
|
||||||
|
|
||||||
gap-1
|
|
||||||
|
|
||||||
overflow-y-auto
|
|
||||||
p-1
|
|
||||||
transition-all
|
|
||||||
|
|
||||||
delay-1000
|
|
||||||
|
|
||||||
duration-200
|
|
||||||
ease-in-out hover:opacity-100
|
|
||||||
hover:delay-500 hover:duration-200
|
|
||||||
dark:bg-blue-800/10
|
|
||||||
"
|
|
||||||
title="
|
|
||||||
ID: {$ae_loc?.person_id ?? '-- not set --'} / {$ae_loc?.user_id ??
|
|
||||||
'-- not set --'}
|
|
||||||
Name: {$ae_loc?.person?.full_name ?? '-- not set --'}
|
|
||||||
Username: {$ae_loc?.user?.username ?? '-- not set --'}
|
|
||||||
Email: {$ae_loc?.user?.email ?? '-- not set --'}
|
|
||||||
Access Type: {$ae_loc?.access_type ?? '-- not set --'}
|
|
||||||
">
|
|
||||||
{#if $ae_loc?.person_id}
|
|
||||||
<div
|
|
||||||
class="group flex w-full flex-row items-center justify-end gap-1 transition-all">
|
|
||||||
<User size="1em" class="mx-1 inline-block text-gray-500" />
|
|
||||||
<span class:hidden={!expand} class="group-hover:inline-block">
|
|
||||||
{$ae_loc?.person?.informal_name ??
|
|
||||||
$ae_loc?.person?.given_name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if $ae_loc?.user_id}
|
|
||||||
<!-- This is currently not set to show if not expanded. Saving space. -->
|
|
||||||
<div
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="group flex w-full flex-row items-center justify-end gap-1 transition-all">
|
|
||||||
<ShieldUser
|
|
||||||
size="1em"
|
|
||||||
class="mx-1 inline-block text-gray-500" />
|
|
||||||
<span class:hidden={!expand} class="group-hover:inline-block">
|
|
||||||
{$ae_loc?.user?.username ?? '-- not set --'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="group flex w-full flex-row items-center justify-end gap-1 transition-all">
|
|
||||||
{#if $ae_loc.access_type && $ae_loc.access_type != 'anonymous'}
|
|
||||||
<span
|
|
||||||
class="group flex flex-row-reverse gap-1 text-base"
|
|
||||||
title={`Current access type/level: ${$ae_loc.access_type}`}>
|
|
||||||
<!-- <span class="fas fa-unlock mx-1"></span> -->
|
|
||||||
<!-- <ShieldPlus class="inline-block" /> -->
|
|
||||||
|
|
||||||
{#if $ae_loc.access_type == 'super'}
|
|
||||||
<Wand2 size="1em" class="m-1 inline-block" />
|
|
||||||
<span
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="hidden group-hover:inline-block">Super</span>
|
|
||||||
{:else if $ae_loc.access_type == 'manager'}
|
|
||||||
<ShieldUser size="1em" class="m-1 inline-block" />
|
|
||||||
<span
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="hidden group-hover:inline-block"
|
|
||||||
>Manager</span>
|
|
||||||
{:else if $ae_loc.access_type == 'administrator'}
|
|
||||||
<UserCog size="1em" class="m-1 inline-block" />
|
|
||||||
<span
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="hidden group-hover:inline-block"
|
|
||||||
>Administrator</span>
|
|
||||||
{:else if $ae_loc.access_type == 'trusted'}
|
|
||||||
<UserCheck size="1em" class="m-1 inline-block" />
|
|
||||||
<span
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="hidden group-hover:inline-block"
|
|
||||||
>Trusted Access</span>
|
|
||||||
{:else if $ae_loc.access_type == 'public'}
|
|
||||||
Public
|
|
||||||
<span
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="hidden group-hover:inline-block"
|
|
||||||
>Access</span>
|
|
||||||
{:else if $ae_loc.access_type == 'authenticated'}
|
|
||||||
Authenticated
|
|
||||||
<span
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="hidden group-hover:inline-block"
|
|
||||||
>Access</span>
|
|
||||||
{:else if $ae_loc.access_type == 'anonymous'}
|
|
||||||
Anonymous Access
|
|
||||||
{:else}
|
|
||||||
Unknown Access
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
{#if $ae_loc?.user_access_type && $ae_loc?.access_type == $ae_loc?.user_access_type}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onclick={() => {
|
|
||||||
// handle_clear_access();
|
|
||||||
// trigger_clear_access = true;
|
|
||||||
// $ae_loc.app_cfg.show_element__passcode_input = !$ae_loc.app_cfg.show_element__passcode_input;
|
|
||||||
|
|
||||||
if (!expand) {
|
|
||||||
expand = true;
|
|
||||||
$ae_sess.sys_menu.expand = true;
|
|
||||||
$ae_loc.sys_menu.hide_access_type = false;
|
|
||||||
$ae_loc.sys_menu.expand_access_type = true;
|
|
||||||
// $ae_loc.sys_menu.expand_btn = false;
|
|
||||||
// $ae_loc.app_cfg.show_element__access_type = true;
|
|
||||||
// $ae_loc.app_cfg.show_element__passcode_input = true;
|
|
||||||
} else {
|
|
||||||
// expand = true;
|
|
||||||
// $ae_loc.sys_menu.expand = false;
|
|
||||||
$ae_loc.sys_menu.hide_access_type = false;
|
|
||||||
$ae_loc.sys_menu.expand_access_type = true;
|
|
||||||
|
|
||||||
// $ae_loc.sys_menu.expand_btn = true;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
class="btn btn-sm variant-outline-surface hover:variant-ghost-warning group text-xs transition-all"
|
|
||||||
title={`Current user access level: "${$ae_loc.user_access_type}". Click use passcode for a different access level.`}>
|
|
||||||
<!-- <span class="fas fa-lock mx-1"></span> -->
|
|
||||||
<!-- <ShieldMinus /> -->
|
|
||||||
<ShieldEllipsis size="2em" class="inline-block" />
|
|
||||||
<span class="hidden group-hover:inline-block"
|
|
||||||
>Passcode?</span>
|
|
||||||
</button>
|
|
||||||
{:else}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onclick={() => {
|
|
||||||
trigger_clear_access = true;
|
|
||||||
|
|
||||||
if (expand) {
|
|
||||||
$ae_loc.sys_menu.hide_access_type = false;
|
|
||||||
// $ae_loc.sys_menu.expand_access_type = false;
|
|
||||||
expand = false;
|
|
||||||
|
|
||||||
// $ae_loc.sys_menu.expand = true;
|
|
||||||
// $ae_loc.sys_menu.expand_btn = false;
|
|
||||||
$ae_loc.app_cfg.show_element__access_type = true;
|
|
||||||
$ae_sess.app_cfg.show_element__passcode_input = true;
|
|
||||||
|
|
||||||
// await tick();
|
|
||||||
// console.log('Layout button click: Focus on passcode input!');
|
|
||||||
// /** @type {HTMLElement | null} */
|
|
||||||
// const to_focus = document.getElementById('access_passcode_input');
|
|
||||||
// to_focus?.focus();
|
|
||||||
} else {
|
|
||||||
$ae_loc.sys_menu.hide_access_type = false;
|
|
||||||
$ae_loc.sys_menu.expand_access_type = true;
|
|
||||||
// $ae_loc.sys_menu.expand = false;
|
|
||||||
// $ae_loc.sys_menu.expand_btn = true;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
class="
|
|
||||||
btn btn-sm variant-outline-surface
|
|
||||||
hover:variant-ghost-warning
|
|
||||||
group flex-row-reverse
|
|
||||||
text-xs transition-all
|
|
||||||
"
|
|
||||||
title={`Current access level: "${$ae_loc.access_type}". Click to clear the temporary access level.`}>
|
|
||||||
<!-- <span class="fas fa-lock mx-1"></span> Lock? -->
|
|
||||||
<ShieldMinus class="inline-block" />
|
|
||||||
<span class="hidden group-hover:inline-block">
|
|
||||||
Clear?
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{:else}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onclick={async () => {
|
|
||||||
expand = true;
|
|
||||||
$ae_sess.sys_menu.expand = true;
|
|
||||||
$ae_loc.sys_menu.hide_access_type = false;
|
|
||||||
$ae_loc.sys_menu.expand_access_type = true;
|
|
||||||
|
|
||||||
$ae_sess.app_cfg.show_element__passcode_input = true;
|
|
||||||
$ae_sess.sys_menu.focus_passcode_input = true;
|
|
||||||
|
|
||||||
// $ae_loc.sys_menu.expand = true;
|
|
||||||
// $ae_loc.sys_menu.expand_btn = false;
|
|
||||||
// $ae_loc.app_cfg.show_element__access_type = true;
|
|
||||||
// $ae_loc.app_cfg.show_element__passcode_input = true;
|
|
||||||
// await tick();
|
|
||||||
console.log(
|
|
||||||
'Layout button click: Focus on passcode input!'
|
|
||||||
);
|
|
||||||
/** @type {HTMLElement | null} */
|
|
||||||
const to_focus = document.getElementById(
|
|
||||||
'access_passcode_input'
|
|
||||||
);
|
|
||||||
to_focus?.focus();
|
|
||||||
}}
|
|
||||||
class="
|
|
||||||
btn btn-sm variant-outline-surface
|
|
||||||
hover:variant-ghost-success
|
|
||||||
group flex-row-reverse
|
|
||||||
text-xs transition-all
|
|
||||||
"
|
|
||||||
title="Anonymous public access is currently set. You must Sign In or use a passcode to change your access level.">
|
|
||||||
<!-- <span class="fas fa-lock mx-1 lock_icon"></span> -->
|
|
||||||
<!-- <span class="">Unlock?</span> -->
|
|
||||||
<ShieldUser class="inline-block" />
|
|
||||||
<span class="hidden group-hover:inline-block">Auth?</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if $ae_loc.edit_mode}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onclick={() => {
|
|
||||||
$ae_loc.edit_mode = false;
|
|
||||||
// dispatch_edit_mode_changed();
|
|
||||||
}}
|
|
||||||
class="
|
|
||||||
btn btn-base preset-tonal-warning
|
|
||||||
preset-outlined-warning-800-200
|
|
||||||
hover:preset-tonal-success
|
|
||||||
group
|
|
||||||
w-full max-w-fit
|
|
||||||
min-w-22 gap-1 text-sm transition-all
|
|
||||||
md:min-w-30
|
|
||||||
"
|
|
||||||
title="Click to turn off edit mode. Edit mode is currently on.">
|
|
||||||
<ToggleRight size="1em" class="m-1 inline-block" />
|
|
||||||
<span class="text-xs">Edit</span>
|
|
||||||
<span
|
|
||||||
class="hidden group-hover:inline-block group-hover:text-xs">
|
|
||||||
Off
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
{:else if $ae_loc.authenticated_access}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onclick={() => {
|
|
||||||
$ae_loc.edit_mode = true;
|
|
||||||
// dispatch_edit_mode_changed();
|
|
||||||
}}
|
|
||||||
class="
|
|
||||||
btn btn-base preset-tonal-surface
|
|
||||||
preset-outlined-warning-400-600
|
|
||||||
hover:preset-tonal-warning
|
|
||||||
group
|
|
||||||
w-full max-w-fit
|
|
||||||
min-w-22 gap-1 text-sm transition-all
|
|
||||||
md:min-w-30
|
|
||||||
"
|
|
||||||
title="Click to torn on/enable edit mode. Edit mode is currently off/disabled.">
|
|
||||||
<ToggleLeft size="1em" class="m-1 inline-block" />
|
|
||||||
<span class="text-xs">Edit</span>
|
|
||||||
<span
|
|
||||||
class="hidden group-hover:inline-block group-hover:text-xs">
|
|
||||||
On?
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- Font Size Cycler: default → larger → smaller → default -->
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class:w-full={expand}
|
|
||||||
class="
|
|
||||||
btn btn-base preset-tonal-surface
|
|
||||||
hover:preset-tonal-primary
|
|
||||||
group
|
|
||||||
w-full max-w-fit
|
|
||||||
min-w-22 px-1 py-1 text-sm
|
|
||||||
transition-all md:min-w-30
|
|
||||||
"
|
|
||||||
title="Cycle font size: default → larger → smaller"
|
|
||||||
onclick={() => {
|
|
||||||
const mode = $ae_loc.font_size_mode;
|
|
||||||
if (!mode || mode === 'default') {
|
|
||||||
$ae_loc.font_size_mode = 'larger';
|
|
||||||
} else if (mode === 'larger') {
|
|
||||||
$ae_loc.font_size_mode = 'smaller';
|
|
||||||
} else {
|
|
||||||
$ae_loc.font_size_mode = 'default';
|
|
||||||
}
|
|
||||||
}}>
|
|
||||||
{#if !$ae_loc.font_size_mode || $ae_loc.font_size_mode === 'default'}
|
|
||||||
<span class="text-sm leading-none font-bold">A</span>
|
|
||||||
<span class="hidden text-xs group-hover:inline-block"
|
|
||||||
>Font: Normal</span>
|
|
||||||
{:else if $ae_loc.font_size_mode === 'larger'}
|
|
||||||
<span class="text-base leading-none font-bold">A+</span>
|
|
||||||
<span class="hidden text-xs group-hover:inline-block"
|
|
||||||
>Font: Larger</span>
|
|
||||||
{:else}
|
|
||||||
<span class="text-xs leading-none font-bold">A−</span>
|
|
||||||
<span class="hidden text-xs group-hover:inline-block"
|
|
||||||
>Font: Smaller</span>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- <div> -->
|
|
||||||
<!-- class:visible={expand} -->
|
|
||||||
<!-- class:invisible={!expand} -->
|
|
||||||
<!-- class:hover:visible={true} -->
|
|
||||||
<!-- invisible -->
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class:w-full={expand}
|
|
||||||
class="
|
|
||||||
btn btn-base preset-filled-tertiary-400-600
|
|
||||||
preset-outlined-tertiary-400-600
|
|
||||||
hover:preset-filled-success
|
|
||||||
active:preset-filled-success group
|
|
||||||
w-full max-w-fit
|
|
||||||
min-w-22 px-1 py-1 text-sm
|
|
||||||
transition-all md:min-w-30
|
|
||||||
"
|
|
||||||
title="Show/Hide the system menu"
|
|
||||||
onclick={async () => {
|
|
||||||
if (!expand) {
|
|
||||||
expand = true;
|
|
||||||
$ae_sess.sys_menu.expand = true;
|
|
||||||
|
|
||||||
// $ae_loc.sys_menu.expand = true;
|
|
||||||
// $ae_loc.sys_menu.expand_btn = false;
|
|
||||||
$ae_loc.app_cfg.show_element__access_type = true;
|
|
||||||
|
|
||||||
if ($ae_loc?.access_type == 'anonymous') {
|
|
||||||
$ae_sess.sys_menu.focus_passcode_input = true;
|
|
||||||
// $ae_sess.app_cfg.show_element__passcode_input = true;
|
|
||||||
} else {
|
|
||||||
// $ae_sess.app_cfg.show_element__passcode_input = false;
|
|
||||||
$ae_loc.sys_menu.expand_user = false; // Not in use yet
|
|
||||||
$ae_sess.show__sign_in_out__fields = false;
|
|
||||||
}
|
|
||||||
// $ae_loc.app_cfg.show_element__passcode_input = true;
|
|
||||||
// await tick();
|
|
||||||
// console.log('Layout button click: Focus on passcode input!');
|
|
||||||
// /** @type {HTMLElement | null} */
|
|
||||||
// const to_focus = document.getElementById('access_passcode_input');
|
|
||||||
// to_focus?.focus();
|
|
||||||
} else {
|
|
||||||
expand = false;
|
|
||||||
$ae_sess.sys_menu.expand = false;
|
|
||||||
// $ae_loc.sys_menu.expand = false;
|
|
||||||
// $ae_loc.sys_menu.expand_btn = true;
|
|
||||||
// $ae_loc.app_cfg.show_element__passcode_input = false;
|
|
||||||
}
|
|
||||||
// $ae_loc.sys_menu.expand_btn = !expand_btn;
|
|
||||||
}}>
|
|
||||||
<!-- <span class=""> -->
|
|
||||||
{#if expand}
|
|
||||||
<CircleX class="m-1 inline-block" />
|
|
||||||
{:else}
|
|
||||||
<Menu class="m-1 inline-block" />
|
|
||||||
{/if}
|
|
||||||
<span class="hidden text-xs group-hover:inline-block"> Menu </span>
|
|
||||||
<!-- </span> -->
|
|
||||||
</button>
|
|
||||||
<!-- </div> -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Show menu on right side of page -->
|
|
||||||
<!-- min-h-96 -->
|
|
||||||
<!-- absolute right-0 bottom-10 -->
|
|
||||||
<!-- opacity-50 -->
|
|
||||||
<!-- hover:opacity-100 -->
|
|
||||||
<!-- bg-white dark:bg-gray-800 -->
|
|
||||||
<div
|
|
||||||
class:preset-filled-warning-200-800={expand}
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="
|
|
||||||
ae_app__sys_menu
|
|
||||||
|
|
||||||
hidden-print
|
|
||||||
z-20 flex
|
|
||||||
min-w-48
|
|
||||||
flex-col
|
|
||||||
items-end
|
|
||||||
|
|
||||||
justify-end
|
|
||||||
|
|
||||||
gap-2 rounded-lg
|
|
||||||
|
|
||||||
border border-gray-200 bg-white
|
|
||||||
px-1
|
|
||||||
py-2 transition-all
|
|
||||||
|
|
||||||
delay-1000
|
|
||||||
duration-100 ease-in-out
|
|
||||||
hover:z-30 hover:delay-100
|
|
||||||
hover:duration-200
|
|
||||||
|
|
||||||
dark:border-gray-700 dark:bg-gray-800
|
|
||||||
">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class:w-full={expand}
|
|
||||||
class="
|
|
||||||
btn btn-sm
|
|
||||||
preset-filled-tertiary-400-600
|
|
||||||
preset-outlined-tertiary-400-600
|
|
||||||
hover:preset-filled-success active:preset-filled-success
|
|
||||||
group px-6
|
|
||||||
py-1 transition-all
|
|
||||||
"
|
|
||||||
title="Show/Hide the system menu"
|
|
||||||
onclick={() => {
|
|
||||||
if (!expand) {
|
|
||||||
expand = true;
|
|
||||||
$ae_sess.sys_menu.expand = true;
|
|
||||||
// $ae_loc.sys_menu.expand_btn = false;
|
|
||||||
// $ae_loc.sys_menu.expand_access_type = true;
|
|
||||||
|
|
||||||
// $ae_sess.app_cfg.show_element__passcode_input = true;
|
|
||||||
$ae_sess.sys_menu.focus_passcode_input = true;
|
|
||||||
} else {
|
|
||||||
$ae_sess.sys_menu.expand = false;
|
|
||||||
$ae_loc.sys_menu.expand_user = false; // Not in use yet
|
|
||||||
$ae_sess.show__sign_in_out__fields = false;
|
|
||||||
// $ae_loc.sys_menu.expand_btn = true;
|
|
||||||
}
|
|
||||||
// $ae_loc.sys_menu.expand_btn = !expand_btn;
|
|
||||||
// $ae_loc.sys_menu.expand = !expand;
|
|
||||||
}}>
|
|
||||||
{#if expand}
|
|
||||||
<CircleX class="m-1 inline-block" />
|
|
||||||
<span class="hidden group-hover:inline-block"> Hide Menu </span>
|
|
||||||
{:else}
|
|
||||||
<Menu class="m-1 inline-block" />
|
|
||||||
<span class="hidden group-hover:inline-block"> Menu </span>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- {#if $ae_loc?.app_cfg?.show_element__cfg} -->
|
|
||||||
<span class:hidden={!$ae_loc.edit_mode}>
|
|
||||||
<Element_app_cfg
|
|
||||||
hide={$ae_loc.sys_menu.hide_app_cfg}
|
|
||||||
expand={$ae_loc.sys_menu.expand_app_cfg} />
|
|
||||||
</span>
|
|
||||||
<span class:hidden={!$ae_loc.edit_mode}>
|
|
||||||
<Element_theme
|
|
||||||
hide={$ae_loc.sys_menu.hide_app_cfg}
|
|
||||||
expand={$ae_loc.sys_menu.expand_app_cfg}
|
|
||||||
set_theme_mode={true}
|
|
||||||
set_theme_name={true} />
|
|
||||||
</span>
|
|
||||||
<!-- {/if} -->
|
|
||||||
|
|
||||||
{#if $ae_loc?.app_cfg?.show_element__sign_in_out}
|
|
||||||
<!-- hide={$ae_loc.sys_menu.hide_user} -->
|
|
||||||
<!-- expand={$ae_loc.sys_menu.expand_user} -->
|
|
||||||
<Element_sign_in_out
|
|
||||||
{data}
|
|
||||||
hidden={$ae_loc.iframe ||
|
|
||||||
!$ae_loc.app_cfg?.show_element__sign_in_out} />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if !$ae_loc?.sys_menu?.hide_access_type && !$ae_loc?.iframe}
|
|
||||||
<!-- hidden={$ae_loc?.iframe && !$ae_loc?.trusted_access && !expand} -->
|
|
||||||
<Element_access_type
|
|
||||||
bind:hide={$ae_loc.sys_menu.hide_access_type}
|
|
||||||
bind:focus_input={$ae_sess.sys_menu.focus_passcode_input}
|
|
||||||
bind:expand={$ae_loc.sys_menu.expand_access_type}
|
|
||||||
bind:show_passcode_input={
|
|
||||||
$ae_sess.app_cfg.show_element__passcode_input
|
|
||||||
}
|
|
||||||
bind:trigger_clear_access />
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
@@ -1,236 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { Minimize2, Moon, Sun } from '@lucide/svelte';
|
|
||||||
import {
|
|
||||||
ae_loc,
|
|
||||||
ae_sess,
|
|
||||||
ae_api,
|
|
||||||
slct,
|
|
||||||
slct_trigger
|
|
||||||
} from '$lib/stores/ae_stores';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
log_lvl?: number;
|
|
||||||
hide?: null | boolean;
|
|
||||||
expand?: boolean;
|
|
||||||
set_theme_mode: any;
|
|
||||||
set_theme_name: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
let {
|
|
||||||
log_lvl = $bindable(0),
|
|
||||||
hide = $bindable(false),
|
|
||||||
expand = $bindable(false),
|
|
||||||
set_theme_mode,
|
|
||||||
set_theme_name
|
|
||||||
}: Props = $props();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Change light and dark mode -->
|
|
||||||
<!--
|
|
||||||
if ($ae_loc.app_cfg.theme_mode == 'light') {
|
|
||||||
document.documentElement.classList.remove('dark');
|
|
||||||
document.documentElement.classList.add('light');
|
|
||||||
} else if ($ae_loc.app_cfg.theme_mode == 'dark') {
|
|
||||||
document.documentElement.classList.remove('light');
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
}
|
|
||||||
-->
|
|
||||||
<section
|
|
||||||
id="AE-App-Theme"
|
|
||||||
class="
|
|
||||||
ae_app_theme
|
|
||||||
hidden-print
|
|
||||||
|
|
||||||
bg-surface-100 dark:bg-surface-800
|
|
||||||
text-surface-900 dark:text-surface-100
|
|
||||||
border-surface-200 dark:border-surface-700 flex
|
|
||||||
|
|
||||||
w-72 max-w-72 flex-col flex-wrap
|
|
||||||
items-end justify-center
|
|
||||||
|
|
||||||
gap-1 rounded-lg
|
|
||||||
border
|
|
||||||
p-1
|
|
||||||
shadow-md
|
|
||||||
|
|
||||||
transition-all delay-150 duration-300 hover:delay-1000
|
|
||||||
hover:ease-out
|
|
||||||
"
|
|
||||||
class:hidden={hide}>
|
|
||||||
<div
|
|
||||||
class:hidden={!expand}
|
|
||||||
class="flex w-full flex-row flex-wrap items-center justify-between gap-2">
|
|
||||||
<!-- Theme Name: -->
|
|
||||||
<span class="text-sm font-semibold">
|
|
||||||
{$ae_loc.theme_name}
|
|
||||||
</span>
|
|
||||||
<select
|
|
||||||
onchange={(event) => {
|
|
||||||
let new_theme_name = (event.target as HTMLInputElement).value;
|
|
||||||
// Update the HTML attribute for Tailwind/Skeleton runtime.
|
|
||||||
document.documentElement.setAttribute('data-theme', new_theme_name);
|
|
||||||
// Persist into the ae_loc store and mark user selection so site defaults don't overwrite.
|
|
||||||
ae_loc.update((l: any) => ({ ...l, theme_name: new_theme_name, user_theme_selected: true }));
|
|
||||||
}}
|
|
||||||
bind:value={$ae_loc.theme_name}
|
|
||||||
class="select w-32"
|
|
||||||
title="Theme name">
|
|
||||||
<option value="">-- None --</option>
|
|
||||||
<option value="cerberus">Cerberus</option>
|
|
||||||
<option value="concord">Concord</option>
|
|
||||||
<option value="crimson">Crimson</option>
|
|
||||||
<option value="hamlindigo">Hamlindigo</option>
|
|
||||||
<option value="modern">Modern</option>
|
|
||||||
<option value="nouveau">Nouveau</option>
|
|
||||||
<option value="rocket">Rocket</option>
|
|
||||||
<option value="terminus">Terminus</option>
|
|
||||||
<option value="vintage">Vintage</option>
|
|
||||||
<option value="wintry">Wintry</option>
|
|
||||||
<!-- <option value="ae_c_osit">OSIT</option> -->
|
|
||||||
<option value="AE_OSIT_default">OSIT</option>
|
|
||||||
<option value="AE_Firefly">Firefly ✦</option>
|
|
||||||
<option value="AE_Firefly_SteelBlue">Firefly SteelBlue ✦</option>
|
|
||||||
<option value="AE_Firefly_Indigo">Firefly Indigo ✦</option>
|
|
||||||
<option value="AE_Firefly_Rainbow">Firefly Rainbow ✨</option>
|
|
||||||
<option value="AE_Firefly_Axonius">Firefly Axonius ✦</option>
|
|
||||||
<option value="AE_Firefly_BGH">Firefly BGH ✦</option>
|
|
||||||
<!-- <option value="AE_Firefly_new-name">Firefly new-name ✦</option> -->
|
|
||||||
<option value="AE_c_IDAA_light">IDAA - light</option>
|
|
||||||
<option value="AE_c_LCI">LCI</option>
|
|
||||||
<option value="AE_c_LCI_new">LCI (New ✦)</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="flex w-full flex-row flex-wrap items-center gap-2"
|
|
||||||
class:justify-between={expand}
|
|
||||||
class:justify-end={!expand}>
|
|
||||||
{#if expand}
|
|
||||||
<!-- Hide theme options -->
|
|
||||||
<button
|
|
||||||
class="
|
|
||||||
btn btn-sm preset-tonal-secondary
|
|
||||||
hover:preset-filled-secondary-500 group
|
|
||||||
text-xs transition-all
|
|
||||||
"
|
|
||||||
onclick={() => {
|
|
||||||
expand = !expand;
|
|
||||||
}}
|
|
||||||
title="Hide Theme Options">
|
|
||||||
<!-- <span class="fas fa-compress-alt"></span> -->
|
|
||||||
<Minimize2 size="1em" class="m-1" />
|
|
||||||
<span
|
|
||||||
class="
|
|
||||||
hidden
|
|
||||||
text-xs
|
|
||||||
group-hover:inline-block
|
|
||||||
">
|
|
||||||
Hide Theme Options
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="
|
|
||||||
btn btn-sm preset-tonal-secondary
|
|
||||||
hover:preset-filled-secondary-500 group
|
|
||||||
text-xs transition-all
|
|
||||||
"
|
|
||||||
onclick={() => {
|
|
||||||
if ($ae_loc.theme_mode == 'light') {
|
|
||||||
$ae_loc.theme_mode = 'dark';
|
|
||||||
} else if ($ae_loc.theme_mode == 'dark') {
|
|
||||||
$ae_loc.theme_mode = 'light';
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOM sync is handled reactively by the layout effect in +layout.svelte
|
|
||||||
}}
|
|
||||||
title="Change light and dark mode">
|
|
||||||
<!-- <span class="fas fa-adjust"></span> -->
|
|
||||||
{#if $ae_loc.theme_mode == 'light'}
|
|
||||||
<Sun class="m-1" />
|
|
||||||
<span
|
|
||||||
class="hidden group-hover:inline-block md:inline-block"
|
|
||||||
>Light Mode</span>
|
|
||||||
{:else if $ae_loc.theme_mode == 'dark'}
|
|
||||||
<Moon class="m-1" />
|
|
||||||
<span class="hidden group-hover:inline-block"
|
|
||||||
>Dark Mode</span>
|
|
||||||
{/if}
|
|
||||||
<span
|
|
||||||
class="
|
|
||||||
hidden
|
|
||||||
text-xs
|
|
||||||
group-hover:inline-block
|
|
||||||
">
|
|
||||||
Change
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
{:else}
|
|
||||||
<button
|
|
||||||
class="btn btn-sm preset-tonal-secondary hover:preset-filled-secondary-500 group"
|
|
||||||
onclick={() => {
|
|
||||||
if ($ae_loc.theme_mode == 'light') {
|
|
||||||
$ae_loc.theme_mode = 'dark';
|
|
||||||
} else if ($ae_loc.theme_mode == 'dark') {
|
|
||||||
$ae_loc.theme_mode = 'light';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($ae_loc.theme_mode == 'light') {
|
|
||||||
document.documentElement.classList.remove('dark');
|
|
||||||
document.documentElement.classList.add('light');
|
|
||||||
} else if ($ae_loc.theme_mode == 'dark') {
|
|
||||||
document.documentElement.classList.remove('light');
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
}
|
|
||||||
|
|
||||||
expand = !expand;
|
|
||||||
}}
|
|
||||||
title="Change light and dark mode">
|
|
||||||
{#if $ae_loc.theme_mode == 'light'}
|
|
||||||
<span class="inline-block" title="Light Mode">
|
|
||||||
<Sun />
|
|
||||||
</span>
|
|
||||||
<span class="hidden group-hover:inline-block"
|
|
||||||
>Light Mode</span>
|
|
||||||
{:else if $ae_loc.theme_mode == 'dark'}
|
|
||||||
<span class="inline-block" title="Dark Mode">
|
|
||||||
<Moon />
|
|
||||||
</span>
|
|
||||||
<span class="hidden group-hover:inline-block"
|
|
||||||
>Dark Mode</span>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <section class="space-y-2">
|
|
||||||
<h2 class="strong">Theme:</h2> -->
|
|
||||||
<!-- Light/Dark Theme: -->
|
|
||||||
<!-- <div>
|
|
||||||
<RadioGroup
|
|
||||||
active="variant-glass-success"
|
|
||||||
hover="hover:variant-ringed-surface"
|
|
||||||
>
|
|
||||||
<RadioItem
|
|
||||||
onchange={() => {
|
|
||||||
$slct_trigger = 'set_theme_mode';
|
|
||||||
}}
|
|
||||||
bind:group={$ae_loc.theme_mode}
|
|
||||||
name="theme_light"
|
|
||||||
value={'light'}
|
|
||||||
>
|
|
||||||
Light
|
|
||||||
</RadioItem>
|
|
||||||
<RadioItem
|
|
||||||
onchange={() => {
|
|
||||||
$slct_trigger = 'set_theme_mode';
|
|
||||||
}}
|
|
||||||
bind:group={$ae_loc.theme_mode}
|
|
||||||
name="theme_dark"
|
|
||||||
value={'dark'}
|
|
||||||
>
|
|
||||||
Dark
|
|
||||||
</RadioItem>
|
|
||||||
</RadioGroup>
|
|
||||||
</div> -->
|
|
||||||
</section>
|
|
||||||
Reference in New Issue
Block a user