|
|
|
|
@ -1,462 +1,927 @@
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
import { AcelConfig, DateRangeField } from '$uix/terra';
|
|
|
|
|
|
|
|
|
|
import { TerraConfig, DateRangeField } from '$uix/terra';
|
|
|
|
|
|
|
|
|
|
import type { DatiDateOrder, DatiTimeFormat } from '$lib/glob/lib';
|
|
|
|
|
|
|
|
|
|
import type { DateValue } from '$lib/glob/lib/date';
|
|
|
|
|
|
|
|
|
|
import { today, getLocalTimeZone, CalendarDate } from '$lib/glob/lib/date';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const tz = getLocalTimeZone();
|
|
|
|
|
|
|
|
|
|
const now = today(tz);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ── Selector de locale global ─────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
const LOCALES: { id: string; label: string; hint: string }[] = [
|
|
|
|
|
|
|
|
|
|
{ id: 'es-ES', label: 'es-ES', hint: 'DD/MM/AAAA' },
|
|
|
|
|
|
|
|
|
|
{ id: 'en-US', label: 'en-US', hint: 'MM/DD/YYYY' },
|
|
|
|
|
|
|
|
|
|
{ id: 'en-GB', label: 'en-GB', hint: 'DD/MM/YYYY' },
|
|
|
|
|
|
|
|
|
|
{ id: 'de-DE', label: 'de-DE', hint: 'TT.MM.JJJJ' },
|
|
|
|
|
|
|
|
|
|
{ id: 'fr-FR', label: 'fr-FR', hint: 'JJ/MM/AAAA' },
|
|
|
|
|
|
|
|
|
|
{ id: 'ja-JP', label: 'ja-JP', hint: 'AAAA/MM/DD' },
|
|
|
|
|
|
|
|
|
|
{ id: 'ar-SA', label: 'ar-SA', hint: 'RTL هـ' },
|
|
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let locale = $state('es-ES');
|
|
|
|
|
|
|
|
|
|
const DATE_ORDERS: DatiDateOrder[] = ['DMY', 'MDY', 'YMD'];
|
|
|
|
|
|
|
|
|
|
const TIME_FORMATS: DatiTimeFormat[] = ['24h', '12h'];
|
|
|
|
|
|
|
|
|
|
let dateOrder = $state<DatiDateOrder>('DMY');
|
|
|
|
|
|
|
|
|
|
let timeFormat = $state<DatiTimeFormat>('24h');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ── 01. Básico ───────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
let value1 = $state<{ start: DateValue | undefined; end: DateValue | undefined } | undefined>(undefined);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ── 02. Pre-seleccionado ─────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
let value2 = $state<{ start: DateValue | undefined; end: DateValue | undefined }>({
|
|
|
|
|
|
|
|
|
|
start: new CalendarDate(now.year, now.month, 5),
|
|
|
|
|
|
|
|
|
|
end: new CalendarDate(now.year, now.month, 20),
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ── 03. Validación ───────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
let value3 = $state<{ start: DateValue | undefined; end: DateValue | undefined } | undefined>(undefined);
|
|
|
|
|
|
|
|
|
|
function validateRange(range: { start: DateValue; end: DateValue }) {
|
|
|
|
|
|
|
|
|
|
const days = Math.round(
|
|
|
|
|
|
|
|
|
|
(range.end.toDate(tz).getTime() - range.start.toDate(tz).getTime()) / 86_400_000
|
|
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (days < 2) return 'El rango debe ser de al menos 2 días';
|
|
|
|
|
|
|
|
|
|
if (days > 30) return 'El rango no puede superar 30 días';
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ── 04. Hora (granularity=hour) ──────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
let value4 = $state<{ start: DateValue | undefined; end: DateValue | undefined } | undefined>(undefined);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ── 05. disabled / readonly ──────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
const fixedVal = {
|
|
|
|
|
|
|
|
|
|
start: new CalendarDate(now.year, now.month, 10),
|
|
|
|
|
|
|
|
|
|
end: new CalendarDate(now.year, now.month, 25),
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ── 06. vía AcelConfig ───────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ── 06. vía TerraConfig ───────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
let value6 = $state<{ start: DateValue | undefined; end: DateValue | undefined } | undefined>(undefined);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function fmt(v: { start?: DateValue; end?: DateValue } | undefined) {
|
|
|
|
|
|
|
|
|
|
if (!v) return '—';
|
|
|
|
|
|
|
|
|
|
const d = (x: DateValue | undefined) =>
|
|
|
|
|
x ? `${x.year}-${String(x.month).padStart(2,'0')}-${String(x.day).padStart(2,'0')}` : '?';
|
|
|
|
|
|
|
|
|
|
x
|
|
|
|
|
? `${x.year}-${String(x.month).padStart(2, '0')}-${String(x.day).padStart(2, '0')}`
|
|
|
|
|
: '?';
|
|
|
|
|
|
|
|
|
|
return `${d(v.start)} → ${d(v.end)}`;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="page">
|
|
|
|
|
|
|
|
|
|
<header class="ph">
|
|
|
|
|
|
|
|
|
|
<div class="ph-inner">
|
|
|
|
|
|
|
|
|
|
<div class="ph-brand">
|
|
|
|
|
|
|
|
|
|
<span class="ph-dot"></span>
|
|
|
|
|
|
|
|
|
|
<span class="ph-title">date-range<em>-field</em></span>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
<span class="ph-sub">acel · campo de entrada de rango de fechas</span>
|
|
|
|
|
|
|
|
|
|
<span class="ph-sub">terra · campo de entrada de rango de fechas</span>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="type-bar">
|
|
|
|
|
|
|
|
|
|
<span class="type-bar-label">Locale:</span>
|
|
|
|
|
|
|
|
|
|
{#each LOCALES as loc}
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
|
|
|
|
|
class="type-btn"
|
|
|
|
|
|
|
|
|
|
class:type-btn--active={locale === loc.id}
|
|
|
|
|
|
|
|
|
|
onclick={() => (locale = loc.id)}
|
|
|
|
|
|
|
|
|
|
title={loc.hint}
|
|
|
|
|
|
|
|
|
|
>{loc.label}</button>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
<span class="type-badge">{LOCALES.find(l => l.id === locale)?.hint ?? ''}</span>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="type-bar type-bar--sub">
|
|
|
|
|
|
|
|
|
|
<span class="type-bar-label">Date order:</span>
|
|
|
|
|
|
|
|
|
|
{#each DATE_ORDERS as order}
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
|
|
|
|
|
class="type-btn"
|
|
|
|
|
|
|
|
|
|
class:type-btn--active={dateOrder === order}
|
|
|
|
|
|
|
|
|
|
onclick={() => (dateOrder = order)}
|
|
|
|
|
|
|
|
|
|
>{order}</button>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<span class="type-bar-label type-bar-label--spaced">Time format:</span>
|
|
|
|
|
|
|
|
|
|
{#each TIME_FORMATS as format}
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
|
|
|
|
|
class="type-btn"
|
|
|
|
|
|
|
|
|
|
class:type-btn--active={timeFormat === format}
|
|
|
|
|
|
|
|
|
|
onclick={() => (timeFormat = format)}
|
|
|
|
|
|
|
|
|
|
>{format}</button>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<main>
|
|
|
|
|
|
|
|
|
|
<div class="grid">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ── 01. Básico ────────────────────────────────────────────── -->
|
|
|
|
|
|
|
|
|
|
<section class="card" data-color="teal">
|
|
|
|
|
|
|
|
|
|
<header class="card-hd">
|
|
|
|
|
|
|
|
|
|
<span class="tag">01</span>
|
|
|
|
|
|
|
|
|
|
<span class="card-title">Básico</span>
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<p class="card-desc">Campo de rango de fechas. Navega con Tab entre segmentos.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="field-wrap">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Root bind:value={value1} {locale} {dateOrder} {timeFormat} class="drf">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Label class="drf-label">Rango de fechas</DateRangeField.Label>
|
|
|
|
|
|
|
|
|
|
<div class="drf-inputs">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="start" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
<span class="drf-sep">→</span>
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="end" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Root>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="val-row">
|
|
|
|
|
|
|
|
|
|
<span class="val-label">value:</span>
|
|
|
|
|
|
|
|
|
|
<span class="val-val">{fmt(value1)}</span>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ── 02. Pre-seleccionado ──────────────────────────────────── -->
|
|
|
|
|
|
|
|
|
|
<section class="card" data-color="violet">
|
|
|
|
|
|
|
|
|
|
<header class="card-hd">
|
|
|
|
|
|
|
|
|
|
<span class="tag">02</span>
|
|
|
|
|
|
|
|
|
|
<span class="card-title">Pre-seleccionado</span>
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<p class="card-desc">Rango cargado con días 5–20 del mes actual.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="field-wrap">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Root bind:value={value2} {locale} {dateOrder} {timeFormat} class="drf">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Label class="drf-label">Rango de fechas</DateRangeField.Label>
|
|
|
|
|
|
|
|
|
|
<div class="drf-inputs">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="start" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
<span class="drf-sep">→</span>
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="end" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Root>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="val-row">
|
|
|
|
|
|
|
|
|
|
<span class="val-label">value:</span>
|
|
|
|
|
|
|
|
|
|
<span class="val-val">{fmt(value2)}</span>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ── 03. Validación ────────────────────────────────────────── -->
|
|
|
|
|
|
|
|
|
|
<section class="card" data-color="amber">
|
|
|
|
|
|
|
|
|
|
<header class="card-hd">
|
|
|
|
|
|
|
|
|
|
<span class="tag">03</span>
|
|
|
|
|
|
|
|
|
|
<span class="card-title">Validación: 2–30 días</span>
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<p class="card-desc">El rango debe tener entre 2 y 30 días.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="field-wrap">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Root bind:value={value3} {locale} {dateOrder} {timeFormat} validate={validateRange} class="drf">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Label class="drf-label">Rango de fechas</DateRangeField.Label>
|
|
|
|
|
|
|
|
|
|
<div class="drf-inputs">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="start" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
<span class="drf-sep">→</span>
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="end" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Root>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="val-row">
|
|
|
|
|
|
|
|
|
|
<span class="val-label">value:</span>
|
|
|
|
|
|
|
|
|
|
<span class="val-val">{fmt(value3)}</span>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ── 04. granularity=hour ──────────────────────────────────── -->
|
|
|
|
|
|
|
|
|
|
<section class="card" data-color="indigo">
|
|
|
|
|
|
|
|
|
|
<header class="card-hd">
|
|
|
|
|
|
|
|
|
|
<span class="tag">04</span>
|
|
|
|
|
|
|
|
|
|
<span class="card-title">granularity="hour"</span>
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<p class="card-desc">Incluye hora de inicio y fin. Alterna entre 12h y 24h.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="field-wrap">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Root bind:value={value4} {locale} {dateOrder} {timeFormat} granularity="hour" class="drf">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Label class="drf-label">Reserva de sala</DateRangeField.Label>
|
|
|
|
|
|
|
|
|
|
<div class="drf-inputs">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="start" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
<span class="drf-sep">→</span>
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="end" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Root>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="val-row">
|
|
|
|
|
|
|
|
|
|
<span class="val-label">value:</span>
|
|
|
|
|
|
|
|
|
|
<span class="val-val">{fmt(value4)}</span>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ── 05. disabled / readonly ───────────────────────────────── -->
|
|
|
|
|
|
|
|
|
|
<section class="card" data-color="rose">
|
|
|
|
|
|
|
|
|
|
<header class="card-hd">
|
|
|
|
|
|
|
|
|
|
<span class="tag">05</span>
|
|
|
|
|
|
|
|
|
|
<span class="card-title">disabled / readonly</span>
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<p class="card-desc">Estados de interacción bloqueada.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="pair-col">
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
|
|
<p class="pair-label">readonly</p>
|
|
|
|
|
|
|
|
|
|
<div class="field-wrap">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Root value={fixedVal} {dateOrder} {timeFormat} readonly class="drf">
|
|
|
|
|
|
|
|
|
|
<div class="drf-inputs">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="start" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
<span class="drf-sep">→</span>
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="end" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Root>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
|
|
|
|
<p class="pair-label">disabled</p>
|
|
|
|
|
|
|
|
|
|
<div class="field-wrap">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Root value={fixedVal} {dateOrder} {timeFormat} disabled class="drf">
|
|
|
|
|
|
|
|
|
|
<div class="drf-inputs">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="start" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
<span class="drf-sep">→</span>
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="end" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Root>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
<!-- ── 06. vía AcelConfig ─────────────────────────────────────── -->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ── 06. vía TerraConfig ─────────────────────────────────────── -->
|
|
|
|
|
|
|
|
|
|
<section class="card" data-color="cyan">
|
|
|
|
|
|
|
|
|
|
<header class="card-hd">
|
|
|
|
|
|
|
|
|
|
<span class="tag">06</span>
|
|
|
|
|
<span class="card-title">Defaults vía AcelConfig</span>
|
|
|
|
|
|
|
|
|
|
<span class="card-title">Defaults vía TerraConfig</span>
|
|
|
|
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
<p class="card-desc">El componente no recibe <code>locale</code>, <code>dateOrder</code> ni <code>timeFormat</code> directamente; los hereda del config reactivo.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="field-wrap">
|
|
|
|
|
<AcelConfig defaultLocale={locale} defaultDateOrder={dateOrder} defaultTimeFormat={timeFormat}>
|
|
|
|
|
|
|
|
|
|
<TerraConfig defaultLocale={locale} defaultDateOrder={dateOrder} defaultTimeFormat={timeFormat}>
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Root bind:value={value6} class="drf">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Label class="drf-label">Rango desde config</DateRangeField.Label>
|
|
|
|
|
|
|
|
|
|
<div class="drf-inputs">
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="start" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
<span class="drf-sep">→</span>
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Input type="end" class="drf-input">
|
|
|
|
|
|
|
|
|
|
{#snippet children({ segments })}
|
|
|
|
|
|
|
|
|
|
{#each segments as { part, value }}
|
|
|
|
|
|
|
|
|
|
<DateRangeField.Segment {part} class="drf-seg drf-seg--{part}">{value}</DateRangeField.Segment>
|
|
|
|
|
|
|
|
|
|
{/each}
|
|
|
|
|
|
|
|
|
|
{/snippet}
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Input>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</DateRangeField.Root>
|
|
|
|
|
</AcelConfig>
|
|
|
|
|
|
|
|
|
|
</TerraConfig>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<div class="val-row">
|
|
|
|
|
|
|
|
|
|
<span class="val-label">value:</span>
|
|
|
|
|
|
|
|
|
|
<span class="val-val">{fmt(value6)}</span>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
</main>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
|
|
|
|
:global(*, *::before, *::after) { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.page {
|
|
|
|
|
|
|
|
|
|
min-height: 100vh; background: #0e0e14; color: #d4d2cc;
|
|
|
|
|
|
|
|
|
|
font-family: 'DM Mono', 'Fira Code', monospace; font-size: 13px;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.ph { border-bottom: 2px solid #818cf8; background: #080810; }
|
|
|
|
|
|
|
|
|
|
.ph-inner {
|
|
|
|
|
|
|
|
|
|
max-width: 1200px; margin: 0 auto; padding: .75rem 1.5rem;
|
|
|
|
|
|
|
|
|
|
display: flex; align-items: center; justify-content: space-between;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ph-brand { display: flex; align-items: center; gap: .5rem; }
|
|
|
|
|
|
|
|
|
|
.ph-dot { width: 8px; height: 8px; border-radius: 50%; background: #818cf8; }
|
|
|
|
|
|
|
|
|
|
.ph-title { font-size: .85rem; font-weight: 700; letter-spacing: .15em; text-transform: uppercase; color: #f4f3ef; }
|
|
|
|
|
|
|
|
|
|
.ph-title em { color: #818cf8; font-style: normal; }
|
|
|
|
|
|
|
|
|
|
.ph-sub { font-size: .65rem; color: #555; letter-spacing: .1em; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main { max-width: 1200px; margin: 0 auto; padding: 1.5rem; }
|
|
|
|
|
|
|
|
|
|
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: .75rem; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.card {
|
|
|
|
|
|
|
|
|
|
background: #16161f; border: 1px solid #26262f; border-radius: 6px;
|
|
|
|
|
|
|
|
|
|
padding: 1.1rem; display: flex; flex-direction: column; gap: .75rem;
|
|
|
|
|
|
|
|
|
|
border-top: 3px solid transparent;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card[data-color="teal"] { border-top-color: #2dd4bf; }
|
|
|
|
|
|
|
|
|
|
.card[data-color="violet"] { border-top-color: #a78bfa; }
|
|
|
|
|
|
|
|
|
|
.card[data-color="amber"] { border-top-color: #e5a100; }
|
|
|
|
|
|
|
|
|
|
.card[data-color="indigo"] { border-top-color: #818cf8; }
|
|
|
|
|
|
|
|
|
|
.card[data-color="rose"] { border-top-color: #fb7185; }
|
|
|
|
|
|
|
|
|
|
.card[data-color="cyan"] { border-top-color: #22d3ee; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.card-hd { display: flex; align-items: center; gap: .5rem; padding-bottom: .6rem; border-bottom: 1px solid #26262f; }
|
|
|
|
|
|
|
|
|
|
.tag { font-size: .6rem; font-weight: 700; letter-spacing: .15em; color: #555; }
|
|
|
|
|
|
|
|
|
|
.card-title { font-size: .75rem; font-weight: 600; color: #aaa; }
|
|
|
|
|
|
|
|
|
|
.card-desc { font-size: .72rem; color: #555; line-height: 1.5; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Field */
|
|
|
|
|
|
|
|
|
|
.field-wrap { display: flex; flex-direction: column; gap: .4rem; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:global(.drf) { display: flex; flex-direction: column; gap: .3rem; }
|
|
|
|
|
|
|
|
|
|
:global(.drf-label) { font-size: .65rem; color: #666; letter-spacing: .08em; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.drf-inputs {
|
|
|
|
|
|
|
|
|
|
display: flex; align-items: center; gap: .4rem;
|
|
|
|
|
|
|
|
|
|
background: #1a1a24; border: 1px solid #26262f; border-radius: 4px;
|
|
|
|
|
|
|
|
|
|
padding: .4rem .6rem;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:global(.drf-input) { display: flex; align-items: center; gap: 1px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.drf-sep { color: #555; font-size: .75rem; flex-shrink: 0; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:global(.drf-seg) {
|
|
|
|
|
|
|
|
|
|
display: inline-block; padding: .05rem .15rem; border-radius: 2px;
|
|
|
|
|
|
|
|
|
|
min-width: 1.6em; text-align: center; font-size: .78rem; color: #d4d2cc;
|
|
|
|
|
|
|
|
|
|
cursor: default; outline: none;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:global(.drf-seg[data-type="literal"]) { color: #444; min-width: auto; padding: 0 1px; }
|
|
|
|
|
|
|
|
|
|
:global(.drf-seg:focus), :global(.drf-seg[data-focused]) {
|
|
|
|
|
|
|
|
|
|
background: #818cf8; color: #fff;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
:global(.drf-seg[data-placeholder]) { color: #555; }
|
|
|
|
|
|
|
|
|
|
:global(.drf[data-readonly] .drf-seg) { pointer-events: none; color: #777; }
|
|
|
|
|
|
|
|
|
|
:global(.drf[data-disabled] .drf-seg) { pointer-events: none; color: #444; opacity: .6; }
|
|
|
|
|
|
|
|
|
|
:global(.drf[data-invalid] .drf-input) { border-color: #fb7185; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Value display */
|
|
|
|
|
|
|
|
|
|
.val-row { display: flex; align-items: center; gap: .5rem; font-size: .72rem; }
|
|
|
|
|
|
|
|
|
|
.val-label { color: #555; }
|
|
|
|
|
|
|
|
|
|
.val-val { font-weight: 700; color: #818cf8; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Pair */
|
|
|
|
|
|
|
|
|
|
.pair-col { display: flex; flex-direction: column; gap: .75rem; }
|
|
|
|
|
|
|
|
|
|
.pair-label { font-size: .62rem; color: #555; margin-bottom: .3rem; letter-spacing: .1em; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Type switcher */
|
|
|
|
|
|
|
|
|
|
.type-bar {
|
|
|
|
|
|
|
|
|
|
max-width: 1200px; margin: 0 auto; padding: .6rem 1.5rem;
|
|
|
|
|
|
|
|
|
|
display: flex; align-items: center; gap: .5rem;
|
|
|
|
|
|
|
|
|
|
border-bottom: 1px solid #26262f;
|
|
|
|
|
|
|
|
|
|
background: #0e0e14;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.type-bar-label { font-size: .65rem; color: #555; letter-spacing: .08em; margin-right: .25rem; }
|
|
|
|
|
|
|
|
|
|
.type-btn {
|
|
|
|
|
|
|
|
|
|
font-family: inherit; font-size: .65rem; letter-spacing: .05em;
|
|
|
|
|
|
|
|
|
|
padding: .2rem .55rem; border-radius: 3px; cursor: pointer;
|
|
|
|
|
|
|
|
|
|
background: #1a1a24; border: 1px solid #26262f; color: #666;
|
|
|
|
|
|
|
|
|
|
transition: border-color .15s, color .15s;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.type-btn:hover { border-color: #818cf8; color: #aaa; }
|
|
|
|
|
|
|
|
|
|
.type-btn--active { border-color: #818cf8; color: #818cf8; background: #1e1e30; }
|
|
|
|
|
|
|
|
|
|
.type-badge { margin-left: auto; font-size: .6rem; color: #2dd4bf; letter-spacing: .1em; }
|
|
|
|
|
|
|
|
|
|
.type-bar--sub { border-top: 1px solid #171720; }
|
|
|
|
|
|
|
|
|
|
.type-bar-label--spaced { margin-left: 1rem; }
|
|
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|