- palco fixo no topo: camera grande com o rosto num quadrinho no canto (toque troca os dois); botao "Ligar camera" direto no palco - controles em lista agrupada estilo Ajustes do iPhone (Grupo, Linha, Interruptor): camera e rastreamento, gestos, aparencia, personalidade - cartao do celular com modelo, Android, versao do app, bateria, Wi-Fi, IP e estado do rosto - APK 0.8.1 informa ip/modelo/android/app/wifi (ACCESS_WIFI_STATE, so o nivel do sinal); servidor usa o IP informado pelo app em vez do endereco da conexao Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
142 lines
3.3 KiB
Svelte
142 lines
3.3 KiB
Svelte
<script lang="ts">
|
|
import { ChevronRight } from '@lucide/svelte';
|
|
import type { Component, Snippet } from 'svelte';
|
|
|
|
// Uma linha da lista: ícone colorido, rótulo, detalhe e um acessório (interruptor, valor ou seta).
|
|
// Com href ou onclick a linha inteira é clicável e mostra a seta.
|
|
let {
|
|
icone,
|
|
cor = 'var(--destaque)',
|
|
rotulo,
|
|
detalhe = '',
|
|
href,
|
|
onclick,
|
|
disabled = false,
|
|
acessorio,
|
|
children,
|
|
}: {
|
|
icone?: Component<any>;
|
|
cor?: string;
|
|
rotulo: string;
|
|
detalhe?: string;
|
|
href?: string;
|
|
onclick?: () => void;
|
|
disabled?: boolean;
|
|
acessorio?: Snippet;
|
|
children?: Snippet;
|
|
} = $props();
|
|
const clicavel = $derived(!!href || !!onclick);
|
|
</script>
|
|
|
|
{#snippet corpo()}
|
|
{#if icone}
|
|
{@const Icone = icone}
|
|
<span class="icone" style="--cor: {cor}" aria-hidden="true"><Icone size={16} strokeWidth={2.4} /></span>
|
|
{/if}
|
|
<span class="texto">
|
|
<span class="rotulo">{rotulo}</span>
|
|
{#if detalhe}<span class="detalhe">{detalhe}</span>{/if}
|
|
</span>
|
|
{#if acessorio}<span class="acessorio">{@render acessorio()}</span>{/if}
|
|
{#if clicavel}<ChevronRight size={18} class="seta" aria-hidden="true" />{/if}
|
|
{/snippet}
|
|
|
|
<div class="linha-ios" class:com-icone={!!icone} class:desativada={disabled}>
|
|
{#if href}
|
|
<a class="conteudo" {href}>{@render corpo()}</a>
|
|
{:else if onclick}
|
|
<button class="conteudo" {onclick} {disabled}>{@render corpo()}</button>
|
|
{:else}
|
|
<div class="conteudo">{@render corpo()}</div>
|
|
{/if}
|
|
{#if children}<div class="extra">{@render children()}</div>{/if}
|
|
</div>
|
|
|
|
<style>
|
|
.linha-ios {
|
|
position: relative;
|
|
}
|
|
/* separador fino que começa depois do ícone, como no iOS */
|
|
.linha-ios:not(:first-child)::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
left: var(--e-4);
|
|
border-top: 1px solid var(--borda);
|
|
}
|
|
.linha-ios.com-icone:not(:first-child)::before {
|
|
left: calc(var(--e-4) + 30px + var(--e-3));
|
|
}
|
|
.conteudo {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--e-3);
|
|
width: 100%;
|
|
min-height: 52px;
|
|
padding: var(--e-2) var(--e-4);
|
|
border: 0;
|
|
background: transparent;
|
|
color: var(--texto);
|
|
font: inherit;
|
|
text-align: left;
|
|
text-decoration: none;
|
|
}
|
|
a.conteudo,
|
|
button.conteudo {
|
|
cursor: pointer;
|
|
}
|
|
a.conteudo:hover,
|
|
button.conteudo:hover:not(:disabled) {
|
|
background: var(--superficie-2);
|
|
}
|
|
a.conteudo:active,
|
|
button.conteudo:active:not(:disabled) {
|
|
background: var(--superficie-3);
|
|
}
|
|
.icone {
|
|
flex: none;
|
|
display: grid;
|
|
place-items: center;
|
|
width: 30px;
|
|
height: 30px;
|
|
border-radius: 8px;
|
|
background: var(--cor);
|
|
color: #fff;
|
|
}
|
|
.texto {
|
|
flex: 1;
|
|
display: grid;
|
|
min-width: 0;
|
|
}
|
|
.rotulo {
|
|
font-size: var(--t-sm);
|
|
font-weight: 500;
|
|
}
|
|
.detalhe {
|
|
font-size: var(--t-xs);
|
|
color: var(--texto-3);
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
.acessorio {
|
|
flex: none;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--e-2);
|
|
color: var(--texto-3);
|
|
font-size: var(--t-sm);
|
|
}
|
|
.conteudo :global(.seta) {
|
|
flex: none;
|
|
color: var(--texto-3);
|
|
}
|
|
.extra {
|
|
padding: 0 var(--e-4) var(--e-4);
|
|
}
|
|
.desativada {
|
|
opacity: 0.5;
|
|
}
|
|
</style>
|