mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-nostr.git
synced 2026-01-27 06:33:18 +00:00
🎨 Add new Flux icons: implement multiple reusable icon components (e.g., hand-raised, hand-thumb-up, heart, hashtag, home) with variant support for improved UI consistency.
This commit is contained in:
@@ -20,36 +20,79 @@
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
/* ----------------------------------------
|
||||
Theme tokens
|
||||
Theme tokens (Einundzwanzig Design System)
|
||||
----------------------------------------- */
|
||||
@theme {
|
||||
--font-sans: "Inconsolata", monospace;
|
||||
|
||||
--color-zinc-50: var(--color-neutral-50);
|
||||
--color-zinc-100: var(--color-neutral-100);
|
||||
--color-zinc-200: var(--color-neutral-200);
|
||||
--color-zinc-300: var(--color-neutral-300);
|
||||
--color-zinc-400: var(--color-neutral-400);
|
||||
--color-zinc-500: var(--color-neutral-500);
|
||||
--color-zinc-600: var(--color-neutral-600);
|
||||
--color-zinc-700: var(--color-neutral-700);
|
||||
--color-zinc-800: var(--color-neutral-800);
|
||||
--color-zinc-900: var(--color-neutral-900);
|
||||
--color-zinc-950: var(--color-neutral-950);
|
||||
/* Background colors */
|
||||
--color-bg-page: #0A0A0B;
|
||||
--color-bg-surface: #111113;
|
||||
--color-bg-elevated: #1A1A1D;
|
||||
|
||||
--color-accent: var(--color-neutral-800);
|
||||
--color-accent-content: var(--color-neutral-800);
|
||||
--color-accent-foreground: var(--color-white);
|
||||
/* Border colors */
|
||||
--color-border-default: #2A2A2E;
|
||||
--color-border-subtle: #1F1F23;
|
||||
|
||||
/* Text colors */
|
||||
--color-text-primary: #FFFFFF;
|
||||
--color-text-secondary: #ADADB0;
|
||||
--color-text-tertiary: #8B8B90;
|
||||
--color-text-muted: #FFFFFFCC;
|
||||
--color-text-disabled: #6B6B70;
|
||||
|
||||
/* Brand colors */
|
||||
--color-orange-primary: #FF5C00;
|
||||
--color-orange-light: #FF8A4C;
|
||||
--color-green-success: #22C55E;
|
||||
--color-purple-accent: #7c3aed;
|
||||
--color-green-nostr: #4a7c59;
|
||||
|
||||
/* Zinc aliases for compatibility */
|
||||
--color-zinc-50: #fafafa;
|
||||
--color-zinc-100: #f4f4f5;
|
||||
--color-zinc-200: #e4e4e7;
|
||||
--color-zinc-300: #d4d4d8;
|
||||
--color-zinc-400: #a1a1aa;
|
||||
--color-zinc-500: #71717a;
|
||||
--color-zinc-600: #52525b;
|
||||
--color-zinc-700: #3f3f46;
|
||||
--color-zinc-800: #27272a;
|
||||
--color-zinc-900: #18181b;
|
||||
--color-zinc-950: #09090b;
|
||||
|
||||
/* Accent colors (orange brand) */
|
||||
--color-accent: var(--color-orange-primary);
|
||||
--color-accent-content: var(--color-orange-primary);
|
||||
--color-accent-foreground: var(--color-text-primary);
|
||||
}
|
||||
|
||||
/* ----------------------------------------
|
||||
Dark mode overrides
|
||||
Dark mode overrides (Dark is default for Einundzwanzig)
|
||||
----------------------------------------- */
|
||||
@layer theme {
|
||||
.dark {
|
||||
--color-accent: var(--color-white);
|
||||
--color-accent-content: var(--color-white);
|
||||
--color-accent-foreground: var(--color-neutral-800);
|
||||
.dark,
|
||||
:root {
|
||||
--color-accent: var(--color-orange-primary);
|
||||
--color-accent-content: var(--color-orange-primary);
|
||||
--color-accent-foreground: var(--color-text-primary);
|
||||
|
||||
/* Flux UI color overrides */
|
||||
--white: var(--color-text-primary);
|
||||
--black: var(--color-bg-page);
|
||||
|
||||
/* Zinc scale for dark mode */
|
||||
--zinc-50: var(--color-bg-elevated);
|
||||
--zinc-100: var(--color-bg-surface);
|
||||
--zinc-200: var(--color-border-default);
|
||||
--zinc-300: var(--color-border-subtle);
|
||||
--zinc-400: var(--color-text-disabled);
|
||||
--zinc-500: var(--color-text-tertiary);
|
||||
--zinc-600: var(--color-text-secondary);
|
||||
--zinc-700: var(--color-text-secondary);
|
||||
--zinc-800: var(--color-text-primary);
|
||||
--zinc-900: var(--color-text-primary);
|
||||
--zinc-950: var(--color-text-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +111,17 @@
|
||||
button {
|
||||
@apply cursor-pointer;
|
||||
}
|
||||
|
||||
/* Ensure body has grid layout for Flux components */
|
||||
body:has(>[data-flux-main]) {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
grid-template-columns: min-content minmax(0, 1fr) min-content;
|
||||
grid-template-areas:
|
||||
"header header header"
|
||||
"sidebar main aside"
|
||||
"sidebar footer aside";
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------
|
||||
@@ -115,3 +169,188 @@ select:focus[data-flux-control] {
|
||||
.leaflet-container a {
|
||||
color: unset !important;
|
||||
}
|
||||
|
||||
/* ----------------------------------------
|
||||
Einundzwanzig Design System - Flux Overrides
|
||||
----------------------------------------- */
|
||||
@layer components {
|
||||
/* Page backgrounds */
|
||||
body {
|
||||
@apply bg-bg-page text-text-primary;
|
||||
}
|
||||
|
||||
/* Cards and surfaces */
|
||||
[data-flux-card] {
|
||||
@apply bg-bg-surface border-border-subtle;
|
||||
}
|
||||
|
||||
/* Primary buttons (orange) */
|
||||
[data-flux-button][data-variant="primary"] {
|
||||
@apply bg-orange-primary text-text-primary hover:bg-orange-light;
|
||||
}
|
||||
|
||||
/* Default/ghost buttons */
|
||||
[data-flux-button]:not([data-variant]) {
|
||||
@apply border-border-default text-text-secondary hover:text-text-primary hover:border-border-default;
|
||||
}
|
||||
|
||||
/* Input fields */
|
||||
[data-flux-input],
|
||||
[data-flux-control] {
|
||||
@apply bg-bg-surface border-border-default text-text-primary placeholder:text-text-disabled;
|
||||
}
|
||||
|
||||
[data-flux-input]:focus,
|
||||
[data-flux-control]:focus {
|
||||
@apply border-orange-primary ring-orange-primary/20;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
[data-flux-navbar] {
|
||||
@apply bg-bg-surface border-b border-border-default;
|
||||
}
|
||||
|
||||
[data-flux-navbar-item][data-current="true"] {
|
||||
@apply border-b-2 border-orange-primary text-text-primary;
|
||||
}
|
||||
|
||||
/* Modals */
|
||||
[data-flux-modal] {
|
||||
@apply bg-bg-surface border-border-subtle;
|
||||
}
|
||||
|
||||
/* Dropdowns/Menus */
|
||||
[data-flux-menu] {
|
||||
@apply bg-bg-elevated border-border-default;
|
||||
}
|
||||
|
||||
[data-flux-menu-item]:hover {
|
||||
@apply bg-bg-surface;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
[data-flux-table] {
|
||||
@apply bg-bg-surface;
|
||||
}
|
||||
|
||||
[data-flux-table] th {
|
||||
@apply bg-bg-elevated text-text-secondary border-border-default;
|
||||
}
|
||||
|
||||
[data-flux-table] td {
|
||||
@apply border-border-subtle text-text-primary;
|
||||
}
|
||||
|
||||
/* Badges */
|
||||
[data-flux-badge] {
|
||||
@apply bg-bg-elevated text-text-secondary border-border-default;
|
||||
}
|
||||
|
||||
[data-flux-badge][data-color="green"] {
|
||||
@apply bg-green-success/20 text-green-success border-green-success/30;
|
||||
}
|
||||
|
||||
[data-flux-badge][data-color="orange"] {
|
||||
@apply bg-orange-primary/20 text-orange-primary border-orange-primary/30;
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
[data-flux-tab][data-selected="true"] {
|
||||
@apply border-orange-primary text-text-primary;
|
||||
}
|
||||
|
||||
/* Switch */
|
||||
[data-flux-switch][data-checked="true"] {
|
||||
@apply bg-orange-primary;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
[data-flux-checkbox]:checked {
|
||||
@apply bg-orange-primary border-orange-primary;
|
||||
}
|
||||
|
||||
/* Radio */
|
||||
[data-flux-radio]:checked {
|
||||
@apply border-orange-primary;
|
||||
}
|
||||
|
||||
[data-flux-radio]:checked::before {
|
||||
@apply bg-orange-primary;
|
||||
}
|
||||
|
||||
/* Separators */
|
||||
[data-flux-separator] {
|
||||
@apply bg-border-default;
|
||||
}
|
||||
|
||||
/* Callouts - Info boxes */
|
||||
.callout-warning {
|
||||
@apply bg-gradient-to-b from-amber-500/20 to-transparent border border-amber-500;
|
||||
}
|
||||
|
||||
.callout-success {
|
||||
@apply bg-gradient-to-b from-green-nostr/20 to-transparent border border-green-nostr;
|
||||
}
|
||||
|
||||
.callout-purple {
|
||||
@apply bg-gradient-to-b from-purple-accent/20 to-transparent border border-purple-accent;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------
|
||||
Einundzwanzig Custom Components
|
||||
----------------------------------------- */
|
||||
@layer components {
|
||||
/* Feature cards with accent borders */
|
||||
.feature-card {
|
||||
@apply bg-bg-surface rounded-xl p-5 border border-border-subtle;
|
||||
}
|
||||
|
||||
.feature-card-nostr {
|
||||
@apply bg-bg-surface rounded-xl p-5 border border-green-nostr;
|
||||
}
|
||||
|
||||
.feature-card-lightning {
|
||||
@apply bg-bg-surface rounded-xl p-5 border border-purple-accent;
|
||||
}
|
||||
|
||||
/* Info boxes with gradients */
|
||||
.info-box {
|
||||
@apply rounded-xl p-4 border;
|
||||
}
|
||||
|
||||
.info-box-warning {
|
||||
@apply rounded-xl p-4 border border-amber-500 bg-gradient-to-b from-amber-500/20 to-transparent;
|
||||
}
|
||||
|
||||
.info-box-success {
|
||||
@apply rounded-xl p-4 border border-green-nostr bg-gradient-to-b from-green-nostr/20 to-transparent;
|
||||
}
|
||||
|
||||
/* Header navigation */
|
||||
.nav-item {
|
||||
@apply px-4 py-3 text-text-secondary hover:text-text-primary transition-colors;
|
||||
}
|
||||
|
||||
.nav-item-active {
|
||||
@apply px-4 py-3 text-text-primary hover:text-text-primary transition-colors border-b-2 border-orange-primary;
|
||||
}
|
||||
|
||||
/* Status badges */
|
||||
.status-badge {
|
||||
@apply inline-flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm;
|
||||
}
|
||||
|
||||
.status-badge-active {
|
||||
@apply inline-flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm bg-green-success/20 text-green-success;
|
||||
}
|
||||
|
||||
.status-badge-pending {
|
||||
@apply inline-flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm bg-amber-500/20 text-amber-500;
|
||||
}
|
||||
|
||||
/* Brand icon container */
|
||||
.brand-icon {
|
||||
@apply w-8 h-8 rounded-lg bg-orange-primary flex items-center justify-center;
|
||||
}
|
||||
}
|
||||
|
||||
38
resources/views/flux/accent.blade.php
Normal file
38
resources/views/flux/accent.blade.php
Normal file
@@ -0,0 +1,38 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'color' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add(match ($color) {
|
||||
'slate' => '[--color-accent:var(--color-slate-800)] [--color-accent-content:var(--color-slate-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-slate-800)]',
|
||||
'gray' => '[--color-accent:var(--color-gray-800)] [--color-accent-content:var(--color-gray-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-gray-800)]',
|
||||
'zinc' => '[--color-accent:var(--color-zinc-800)] [--color-accent-content:var(--color-zinc-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-zinc-800)]',
|
||||
'neutral' => '[--color-accent:var(--color-neutral-800)] [--color-accent-content:var(--color-neutral-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-neutral-800)]',
|
||||
'stone' => '[--color-accent:var(--color-stone-800)] [--color-accent-content:var(--color-stone-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-stone-800)]',
|
||||
'red' => '[--color-accent:var(--color-red-500)] [--color-accent-content:var(--color-red-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-red-500)] dark:[--color-accent-content:var(--color-red-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'orange' => '[--color-accent:var(--color-orange-500)] [--color-accent-content:var(--color-orange-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-orange-400)] dark:[--color-accent-content:var(--color-orange-400)] dark:[--color-accent-foreground:var(--color-orange-950)]',
|
||||
'amber' => '[--color-accent:var(--color-amber-400)] [--color-accent-content:var(--color-amber-600)] [--color-accent-foreground:var(--color-amber-950)] dark:[--color-accent:var(--color-amber-400)] dark:[--color-accent-content:var(--color-amber-400)] dark:[--color-accent-foreground:var(--color-amber-950)]',
|
||||
'yellow' => '[--color-accent:var(--color-yellow-400)] [--color-accent-content:var(--color-yellow-600)] [--color-accent-foreground:var(--color-yellow-950)] dark:[--color-accent:var(--color-yellow-400)] dark:[--color-accent-content:var(--color-yellow-400)] dark:[--color-accent-foreground:var(--color-yellow-950)]',
|
||||
'lime' => '[--color-accent:var(--color-lime-400)] [--color-accent-content:var(--color-lime-600)] [--color-accent-foreground:var(--color-lime-900)] dark:[--color-accent:var(--color-lime-400)] dark:[--color-accent-content:var(--color-lime-400)] dark:[--color-accent-foreground:var(--color-lime-950)]',
|
||||
'green' => '[--color-accent:var(--color-green-600)] [--color-accent-content:var(--color-green-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-green-600)] dark:[--color-accent-content:var(--color-green-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'emerald' => '[--color-accent:var(--color-emerald-600)] [--color-accent-content:var(--color-emerald-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-emerald-600)] dark:[--color-accent-content:var(--color-emerald-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'teal' => '[--color-accent:var(--color-teal-600)] [--color-accent-content:var(--color-teal-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-teal-600)] dark:[--color-accent-content:var(--color-teal-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'cyan' => '[--color-accent:var(--color-cyan-600)] [--color-accent-content:var(--color-cyan-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-cyan-600)] dark:[--color-accent-content:var(--color-cyan-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'sky' => '[--color-accent:var(--color-sky-600)] [--color-accent-content:var(--color-sky-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-sky-600)] dark:[--color-accent-content:var(--color-sky-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'blue' => '[--color-accent:var(--color-blue-500)] [--color-accent-content:var(--color-blue-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-blue-500)] dark:[--color-accent-content:var(--color-blue-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'indigo' => '[--color-accent:var(--color-indigo-500)] [--color-accent-content:var(--color-indigo-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-indigo-500)] dark:[--color-accent-content:var(--color-indigo-300)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'violet' => '[--color-accent:var(--color-violet-500)] [--color-accent-content:var(--color-violet-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-violet-500)] dark:[--color-accent-content:var(--color-violet-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'purple' => '[--color-accent:var(--color-purple-500)] [--color-accent-content:var(--color-purple-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-purple-500)] dark:[--color-accent-content:var(--color-purple-300)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'fuchsia' => '[--color-accent:var(--color-fuchsia-600)] [--color-accent-content:var(--color-fuchsia-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-fuchsia-600)] dark:[--color-accent-content:var(--color-fuchsia-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'pink' => '[--color-accent:var(--color-pink-600)] [--color-accent-content:var(--color-pink-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-pink-600)] dark:[--color-accent-content:var(--color-pink-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'rose' => '[--color-accent:var(--color-rose-500)] [--color-accent-content:var(--color-rose-500)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-rose-500)] dark:[--color-accent-content:var(--color-rose-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
})
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
23
resources/views/flux/accordion/content.blade.php
Normal file
23
resources/views/flux/accordion/content.blade.php
Normal file
@@ -0,0 +1,23 @@
|
||||
@aware([ 'transition', 'expanded' ])
|
||||
|
||||
@props([
|
||||
'transition' => false,
|
||||
'expanded' => false,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('pt-2 text-sm text-zinc-500 dark:text-zinc-300')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div
|
||||
x-show="open"
|
||||
@if ($transition) x-collapse @endif
|
||||
@if (! $expanded) x-cloak @endif
|
||||
data-flux-accordion-content
|
||||
>
|
||||
<div {{ $attributes->class($classes) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
33
resources/views/flux/accordion/heading.blade.php
Normal file
33
resources/views/flux/accordion/heading.blade.php
Normal file
@@ -0,0 +1,33 @@
|
||||
@aware([ 'disabled', 'variant' ])
|
||||
|
||||
@props([
|
||||
'disabled' => null,
|
||||
'variant' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('group/accordion-heading flex items-center w-full')
|
||||
->add('text-start text-sm font-medium')
|
||||
->add(match ($variant) {
|
||||
default => 'justify-between [&>svg]:ms-6',
|
||||
'reverse' => 'flex-row-reverse justify-end [&>svg]:me-2',
|
||||
})
|
||||
->add($disabled
|
||||
? 'text-zinc-400 dark:text-zinc-400 cursor-default'
|
||||
: 'text-zinc-800 dark:text-white cursor-pointer'
|
||||
)
|
||||
;
|
||||
@endphp
|
||||
|
||||
<button type="button" {{ $attributes->class($classes) }} @if ($disabled) disabled @endif data-flux-accordion-heading>
|
||||
<span class="flex-1">{{ $slot }}</span>
|
||||
|
||||
<?php if ($variant === 'reverse'): ?>
|
||||
<flux:accordion.icon pointing="down" class="hidden group-data-open/accordion-heading:block text-zinc-800! dark:text-white!" />
|
||||
<flux:accordion.icon pointing="right" class="block group-data-open/accordion-heading:hidden" />
|
||||
<?php else: ?>
|
||||
<flux:accordion.icon pointing="up" class="hidden group-data-open/accordion-heading:block text-zinc-800! dark:text-white!" />
|
||||
<flux:accordion.icon pointing="down" class="block group-data-open/accordion-heading:hidden" />
|
||||
<?php endif; ?>
|
||||
</button>
|
||||
17
resources/views/flux/accordion/icon.blade.php
Normal file
17
resources/views/flux/accordion/icon.blade.php
Normal file
@@ -0,0 +1,17 @@
|
||||
@aware([ 'disabled' ])
|
||||
|
||||
@props([
|
||||
'pointing' => 'down',
|
||||
'disabled' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('text-zinc-300 dark:text-zinc-400')
|
||||
->add($disabled ? ''
|
||||
: 'group-hover/accordion-heading:text-zinc-800 dark:group-hover/accordion-heading:text-white'
|
||||
)
|
||||
;
|
||||
@endphp
|
||||
|
||||
<flux:icon :icon="'chevron-'.$pointing" variant="mini" aria-hidden="true" :attributes="$attributes->class($classes)" />
|
||||
9
resources/views/flux/accordion/index.blade.php
Normal file
9
resources/views/flux/accordion/index.blade.php
Normal file
@@ -0,0 +1,9 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'variant' => null,
|
||||
])
|
||||
|
||||
<ui-disclosure-group {{ $attributes->class('block') }} data-flux-accordion-heading>
|
||||
{{ $slot }}
|
||||
</ui-disclosure-group>
|
||||
42
resources/views/flux/accordion/item.blade.php
Normal file
42
resources/views/flux/accordion/item.blade.php
Normal file
@@ -0,0 +1,42 @@
|
||||
@aware([ 'transition' ])
|
||||
|
||||
@props([
|
||||
'transition' => false,
|
||||
'disabled' => false,
|
||||
'expanded' => false,
|
||||
'heading' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
// Support adding the .self modifier to the wire:model directive...
|
||||
if (($wireModel = $attributes->wire('model')) && $wireModel->directive && ! $wireModel->hasModifier('self')) {
|
||||
unset($attributes[$wireModel->directive]);
|
||||
|
||||
$wireModel->directive .= '.self';
|
||||
|
||||
$attributes = $attributes->merge([$wireModel->directive => $wireModel->value]);
|
||||
}
|
||||
|
||||
// Support binding the state to a Livewire property
|
||||
$state = $wireModel?->value ? '$wire.' . $wireModel->value : ($expanded ? 'true' : 'false');
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('block pt-4 first:pt-0 pb-4 last:pb-0')
|
||||
->add('border-b last:border-b-0 border-zinc-800/10 dark:border-white/10')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<ui-disclosure
|
||||
{{ $attributes->class($classes) }}
|
||||
x-data="{ open: {{ $state }} }"
|
||||
x-model.self="open"
|
||||
data-flux-accordion-item
|
||||
>
|
||||
<?php if ($heading): ?>
|
||||
<flux:accordion.heading>{{ $heading }}</flux:accordion.heading>
|
||||
|
||||
<flux:accordion.content>{{ $slot }}</flux:accordion.content>
|
||||
<?php else: ?>
|
||||
{{ $slot }}
|
||||
<?php endif; ?>
|
||||
</ui-disclosure>
|
||||
21
resources/views/flux/aside.blade.php
Normal file
21
resources/views/flux/aside.blade.php
Normal file
@@ -0,0 +1,21 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'sticky' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes('[grid-area:aside]');
|
||||
|
||||
if ($sticky) {
|
||||
$attributes = $attributes->merge([
|
||||
'x-data' => '',
|
||||
'x-bind:style' => '{ position: \'sticky\', top: $el.offsetTop + \'px\', \'max-height\': \'calc(100dvh - \' + $el.offsetTop + \'px)\' }',
|
||||
'class' => 'max-h-[100vh] overflow-y-auto',
|
||||
]);
|
||||
}
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }} data-flux-aside>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
15
resources/views/flux/autocomplete/index.blade.php
Normal file
15
resources/views/flux/autocomplete/index.blade.php
Normal file
@@ -0,0 +1,15 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'filter' => true,
|
||||
'disabled' => false,
|
||||
])
|
||||
|
||||
<?php $containerAttributes = Flux::attributesAfter('container:', $attributes); ?>
|
||||
<ui-select autocomplete clear="esc" data-flux-autocomplete {{ $containerAttributes->merge(['filter' => $filter, 'disabled' => $disabled]) }}>
|
||||
<flux:input :attributes="$attributes->except('filter')" />
|
||||
|
||||
<flux:autocomplete.items>
|
||||
{{ $slot }}
|
||||
</flux:autocomplete.items>
|
||||
</ui-select>
|
||||
14
resources/views/flux/autocomplete/item.blade.php
Normal file
14
resources/views/flux/autocomplete/item.blade.php
Normal file
@@ -0,0 +1,14 @@
|
||||
@blaze
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('data-hidden:hidden flex items-center px-2 py-1.5 w-full focus:outline-hidden rounded-md')
|
||||
->add('text-start text-sm font-medium')
|
||||
->add('text-zinc-800 data-active:bg-zinc-100 dark:text-white dark:data-active:bg-zinc-600')
|
||||
->add('scroll-my-[.3125rem]') // This is here so that when a user scrolls to the top or bottom of the list, the padding is included...
|
||||
;
|
||||
@endphp
|
||||
|
||||
<ui-option {{ $attributes->class($classes) }} data-flux-autocomplete-item>
|
||||
{{ $slot }}
|
||||
</ui-option>
|
||||
17
resources/views/flux/autocomplete/items.blade.php
Normal file
17
resources/views/flux/autocomplete/items.blade.php
Normal file
@@ -0,0 +1,17 @@
|
||||
@blaze
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('[:where(&)]:max-h-[20rem]') // "[:where(&)]:" means it can be overriden without "!"...
|
||||
->add('p-[.3125rem] overflow-y-auto rounded-lg shadow-xs')
|
||||
->add('border border-zinc-200 dark:border-zinc-600')
|
||||
->add('bg-white dark:bg-zinc-700')
|
||||
->add('[&:not(:has(ui-empty[data-hidden]))]:hidden') // Hide this entire panel if there are no results...
|
||||
;
|
||||
@endphp
|
||||
|
||||
<ui-options popover="manual" {{ $attributes->class($classes) }} data-flux-autocomplete-items>
|
||||
{{ $slot }}
|
||||
|
||||
<ui-empty class="contents"></ui-empty>
|
||||
</ui-options>
|
||||
13
resources/views/flux/avatar/group.blade.php
Normal file
13
resources/views/flux/avatar/group.blade.php
Normal file
@@ -0,0 +1,13 @@
|
||||
@blaze
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('flex isolate')
|
||||
->add('*:not-first:-ml-2 **:ring-white **:dark:ring-zinc-900')
|
||||
->add('**:data-[slot=avatar]:ring-4 **:data-[slot=avatar]:data-[size=sm]:ring-2 **:data-[slot=avatar]:data-[size=xs]:ring-2')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
189
resources/views/flux/avatar/index.blade.php
Normal file
189
resources/views/flux/avatar/index.blade.php
Normal file
@@ -0,0 +1,189 @@
|
||||
@blaze
|
||||
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'iconVariant' => 'solid',
|
||||
'initials' => null,
|
||||
'tooltip' => null,
|
||||
'circle' => null,
|
||||
'color' => null,
|
||||
'badge' => null,
|
||||
'name' => null,
|
||||
'icon' => null,
|
||||
'size' => 'md',
|
||||
'src' => null,
|
||||
'href' => null,
|
||||
'alt' => null,
|
||||
'as' => 'div',
|
||||
])
|
||||
|
||||
@php
|
||||
if ($name && ! $initials) {
|
||||
$parts = explode(' ', trim($name));
|
||||
|
||||
if ($attributes->pluck('initials:single')) {
|
||||
$initials = strtoupper(mb_substr($parts[0], 0, 1));
|
||||
} else {
|
||||
// Remove empty strings from the array...
|
||||
$parts = collect($parts)->filter()->values()->all();
|
||||
|
||||
if (count($parts) > 1) {
|
||||
$initials = strtoupper(mb_substr($parts[0], 0, 1) . mb_substr($parts[1], 0, 1));
|
||||
} else if (count($parts) === 1) {
|
||||
$initials = strtoupper(mb_substr($parts[0], 0, 1)) . strtolower(mb_substr($parts[0], 1, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($name && $tooltip === true) {
|
||||
$tooltip = $name;
|
||||
}
|
||||
|
||||
$hasTextContent = $icon ?? $initials ?? $slot->isNotEmpty();
|
||||
|
||||
// If there's no text content, we'll fallback to using the user icon otherwise there will be an empty white square...
|
||||
if (! $hasTextContent) {
|
||||
$icon = 'user';
|
||||
$hasTextContent = true;
|
||||
}
|
||||
|
||||
// Be careful not to change the order of these colors.
|
||||
// They're used in the hash function below and changing them would change actual user avatar colors that they might have grown to identify with.
|
||||
$colors = ['red', 'orange', 'amber', 'yellow', 'lime', 'green', 'emerald', 'teal', 'cyan', 'sky', 'blue', 'indigo', 'violet', 'purple', 'fuchsia', 'pink', 'rose'];
|
||||
|
||||
if ($hasTextContent && $color === 'auto') {
|
||||
$colorSeed = $attributes->pluck('color:seed') ?? $name ?? $icon ?? $initials ?? $slot;
|
||||
$hash = crc32((string) $colorSeed);
|
||||
$color = $colors[$hash % count($colors)];
|
||||
}
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add(match($size) {
|
||||
'xl' => '[:where(&)]:size-16 [:where(&)]:text-base',
|
||||
'lg' => '[:where(&)]:size-12 [:where(&)]:text-base',
|
||||
default => '[:where(&)]:size-10 [:where(&)]:text-sm',
|
||||
'sm' => '[:where(&)]:size-8 [:where(&)]:text-sm',
|
||||
'xs' => '[:where(&)]:size-6 [:where(&)]:text-xs',
|
||||
})
|
||||
->add($circle ? '[--avatar-radius:calc(infinity*1px)]' : match($size) {
|
||||
'xl' => '[--avatar-radius:var(--radius-xl)]',
|
||||
'lg' => '[--avatar-radius:var(--radius-lg)]',
|
||||
default => '[--avatar-radius:var(--radius-lg)]',
|
||||
'sm' => '[--avatar-radius:var(--radius-md)]',
|
||||
'xs' => '[--avatar-radius:var(--radius-sm)]',
|
||||
})
|
||||
->add('relative flex-none isolate flex items-center justify-center')
|
||||
->add('[:where(&)]:font-medium')
|
||||
->add('rounded-[var(--avatar-radius)]')
|
||||
->add($hasTextContent ? '[:where(&)]:bg-zinc-200 [:where(&)]:dark:bg-zinc-600 [:where(&)]:text-zinc-800 [:where(&)]:dark:text-white' : '')
|
||||
->add(match($color) {
|
||||
'red' => 'bg-red-200 text-red-800',
|
||||
'orange' => 'bg-orange-200 text-orange-800',
|
||||
'amber' => 'bg-amber-200 text-amber-800',
|
||||
'yellow' => 'bg-yellow-200 text-yellow-800',
|
||||
'lime' => 'bg-lime-200 text-lime-800',
|
||||
'green' => 'bg-green-200 text-green-800',
|
||||
'emerald' => 'bg-emerald-200 text-emerald-800',
|
||||
'teal' => 'bg-teal-200 text-teal-800',
|
||||
'cyan' => 'bg-cyan-200 text-cyan-800',
|
||||
'sky' => 'bg-sky-200 text-sky-800',
|
||||
'blue' => 'bg-blue-200 text-blue-800',
|
||||
'indigo' => 'bg-indigo-200 text-indigo-800',
|
||||
'violet' => 'bg-violet-200 text-violet-800',
|
||||
'purple' => 'bg-purple-200 text-purple-800',
|
||||
'fuchsia' => 'bg-fuchsia-200 text-fuchsia-800',
|
||||
'pink' => 'bg-pink-200 text-pink-800',
|
||||
'rose' => 'bg-rose-200 text-rose-800',
|
||||
default => '',
|
||||
})
|
||||
->add(true ? [
|
||||
'after:absolute after:inset-0 after:inset-ring-[1px] after:inset-ring-black/7 dark:after:inset-ring-white/10',
|
||||
$circle ? 'after:rounded-full' : match($size) {
|
||||
'xl' => 'after:rounded-xl',
|
||||
'lg' => 'after:rounded-lg',
|
||||
default => 'after:rounded-lg',
|
||||
'sm' => 'after:rounded-md',
|
||||
'xs' => 'after:rounded-sm',
|
||||
},
|
||||
] : []);
|
||||
|
||||
$iconClasses = Flux::classes()
|
||||
->add('opacity-75')
|
||||
->add(match($size) {
|
||||
'lg' => 'size-8',
|
||||
default => 'size-6',
|
||||
'sm' => 'size-5',
|
||||
'xs' => 'size-4',
|
||||
});
|
||||
|
||||
$badgeColor = $attributes->pluck('badge:color') ?: (is_object($badge) ? $badge?->attributes?->pluck('color') : null);
|
||||
$badgeCircle = $attributes->pluck('badge:circle') ?: (is_object($badge) ? $badge?->attributes?->pluck('circle') : null);
|
||||
$badgePosition = $attributes->pluck('badge:position') ?: (is_object($badge) ? $badge?->attributes?->pluck('position') : null);
|
||||
$badgeVariant = $attributes->pluck('badge:variant') ?: (is_object($badge) ? $badge?->attributes?->pluck('variant') : null);
|
||||
|
||||
$badgeClasses = Flux::classes()
|
||||
->add('absolute ring-[2px] ring-white dark:ring-zinc-900 z-10')
|
||||
->add(match($size) {
|
||||
default => 'h-3 min-w-3',
|
||||
'sm' => 'h-2 min-w-2',
|
||||
'xs' => 'h-2 min-w-2',
|
||||
})
|
||||
->add('flex items-center justify-center tabular-nums overflow-hidden')
|
||||
->add('text-[.625rem] text-zinc-800 dark:text-white font-medium')
|
||||
->add($badgeCircle ? 'rounded-full' : 'rounded-[3px]')
|
||||
->add($badgeVariant === 'outline' ? [
|
||||
'after:absolute after:inset-[3px] after:bg-white dark:after:bg-zinc-900',
|
||||
$badgeCircle ? 'after:rounded-full' : 'after:rounded-[1px]',
|
||||
] : [])
|
||||
->add(match($badgePosition) {
|
||||
'top left' => 'top-0 left-0',
|
||||
'top right' => 'top-0 right-0',
|
||||
'bottom left' => 'bottom-0 left-0',
|
||||
'bottom right' => 'bottom-0 right-0',
|
||||
default => 'bottom-0 right-0',
|
||||
})
|
||||
->add(match($badgeColor) {
|
||||
'red' => 'bg-red-500 dark:bg-red-400',
|
||||
'orange' => 'bg-orange-500 dark:bg-orange-400',
|
||||
'amber' => 'bg-amber-500 dark:bg-amber-400',
|
||||
'yellow' => 'bg-yellow-500 dark:bg-yellow-400',
|
||||
'lime' => 'bg-lime-500 dark:bg-lime-400',
|
||||
'green' => 'bg-green-500 dark:bg-green-400',
|
||||
'emerald' => 'bg-emerald-500 dark:bg-emerald-400',
|
||||
'teal' => 'bg-teal-500 dark:bg-teal-400',
|
||||
'cyan' => 'bg-cyan-500 dark:bg-cyan-400',
|
||||
'sky' => 'bg-sky-500 dark:bg-sky-400',
|
||||
'blue' => 'bg-blue-500 dark:bg-blue-400',
|
||||
'indigo' => 'bg-indigo-500 dark:bg-indigo-400',
|
||||
'violet' => 'bg-violet-500 dark:bg-violet-400',
|
||||
'purple' => 'bg-purple-500 dark:bg-purple-400',
|
||||
'fuchsia' => 'bg-fuchsia-500 dark:bg-fuchsia-400',
|
||||
'pink' => 'bg-pink-500 dark:bg-pink-400',
|
||||
'rose' => 'bg-rose-500 dark:bg-rose-400',
|
||||
'zinc' => 'bg-zinc-400 dark:bg-zinc-300',
|
||||
'gray' => 'bg-zinc-400 dark:bg-zinc-300',
|
||||
default => 'bg-white dark:bg-zinc-900',
|
||||
})
|
||||
;
|
||||
|
||||
$label = $alt ?? $name;
|
||||
@endphp
|
||||
|
||||
<flux:with-tooltip :$tooltip :$attributes>
|
||||
<flux:button-or-link :attributes="$attributes->class($classes)->merge($circle ? ['data-circle' => 'true'] : [])" :$as :$href data-flux-avatar data-slot="avatar" data-size="{{ $size }}">
|
||||
<?php if ($src): ?>
|
||||
<img src="{{ $src }}" alt="{{ $alt ?? $name }}" class="rounded-[var(--avatar-radius)] size-full object-cover">
|
||||
<?php elseif ($icon): ?>
|
||||
<flux:icon :name="$icon" :variant="$iconVariant" :class="$iconClasses" />
|
||||
<?php elseif ($hasTextContent): ?>
|
||||
<span class="select-none">{{ $initials ?? $slot }}</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($badge instanceof \Illuminate\View\ComponentSlot): ?>
|
||||
<div {{ $badge->attributes->class($badgeClasses) }} aria-hidden="true">{{ $badge }}</div>
|
||||
<?php elseif ($badge): ?>
|
||||
<div class="{{ $badgeClasses }}" aria-hidden="true">{{ is_string($badge) ? $badge : '' }}</div>
|
||||
<?php endif; ?>
|
||||
</flux:button-or-link>
|
||||
</flux:with-tooltip>
|
||||
25
resources/views/flux/badge/close.blade.php
Normal file
25
resources/views/flux/badge/close.blade.php
Normal file
@@ -0,0 +1,25 @@
|
||||
@blaze
|
||||
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'iconVariant' => 'micro',
|
||||
'icon' => 'x-mark',
|
||||
])
|
||||
|
||||
@php
|
||||
// When using the outline icon variant, we need to size it down to match the default icon sizes...
|
||||
$iconClasses = Flux::classes()->add($iconVariant === 'outline' ? 'size-4' : '');
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('p-1 -my-1 -me-1 opacity-50 hover:opacity-100')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<button type="button" {{ $attributes->class($classes) }} data-flux-badge-close>
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<flux:icon :$icon :variant="$iconVariant" :class="$iconClasses" />
|
||||
<?php else: ?>
|
||||
{{ $icon }}
|
||||
<?php endif; ?>
|
||||
</button>
|
||||
98
resources/views/flux/badge/index.blade.php
Normal file
98
resources/views/flux/badge/index.blade.php
Normal file
@@ -0,0 +1,98 @@
|
||||
@blaze
|
||||
|
||||
@php $iconTrailing ??= $attributes->pluck('icon:trailing'); @endphp
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'iconVariant' => 'micro',
|
||||
'iconTrailing' => null,
|
||||
'variant' => null,
|
||||
'color' => null,
|
||||
'inset' => null,
|
||||
'size' => null,
|
||||
'icon' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$insetClasses = Flux::applyInset($inset, top: '-mt-1', right: '-me-2', bottom: '-mb-1', left: '-ms-2');
|
||||
|
||||
// When using the outline icon variant, we need to size it down to match the default icon sizes...
|
||||
$iconClasses = Flux::classes()->add($iconVariant === 'outline' ? 'size-4' : '');
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('inline-flex items-center font-medium whitespace-nowrap')
|
||||
->add($insetClasses)
|
||||
->add('[print-color-adjust:exact]')
|
||||
->add(match ($size) {
|
||||
'lg' => 'text-sm py-1.5 **:data-flux-badge-icon:me-2',
|
||||
default => 'text-sm py-1 **:data-flux-badge-icon:me-1.5',
|
||||
'sm' => 'text-xs py-1 **:data-flux-badge-icon:size-3 **:data-flux-badge-icon:me-1',
|
||||
})
|
||||
->add(match ($variant) {
|
||||
'pill' => 'rounded-full px-3',
|
||||
default => 'rounded-md px-2',
|
||||
})
|
||||
/**
|
||||
* We can't compile classes for each color because of variants color to color and Tailwind's JIT compiler.
|
||||
* We instead need to write out each one by hand. Sorry...
|
||||
*/
|
||||
->add($variant === 'solid' ? match ($color) {
|
||||
default => 'text-text-primary bg-bg-elevated [&:is(button)]:hover:bg-bg-surface',
|
||||
'red' => 'text-white dark:text-white bg-red-500 dark:bg-red-600 [&:is(button)]:hover:bg-red-600 dark:[button]:hover:bg-red-500',
|
||||
'orange' => 'text-white dark:text-white bg-orange-500 dark:bg-orange-600 [&:is(button)]:hover:bg-orange-600 dark:[button]:hover:bg-orange-500',
|
||||
'amber' => 'text-white dark:text-zinc-950 bg-amber-500 dark:bg-amber-500 [&:is(button)]:hover:bg-amber-600 dark:[button]:hover:bg-amber-400',
|
||||
'yellow' => 'text-white dark:text-zinc-950 bg-yellow-500 dark:bg-yellow-400 [&:is(button)]:hover:bg-yellow-600 dark:[button]:hover:bg-yellow-300',
|
||||
'lime' => 'text-white dark:text-white bg-lime-500 dark:bg-lime-600 [&:is(button)]:hover:bg-lime-600 dark:[button]:hover:bg-lime-500',
|
||||
'green' => 'text-white dark:text-white bg-green-500 dark:bg-green-600 [&:is(button)]:hover:bg-green-600 dark:[button]:hover:bg-green-500',
|
||||
'emerald' => 'text-white dark:text-white bg-emerald-500 dark:bg-emerald-600 [&:is(button)]:hover:bg-emerald-600 dark:[button]:hover:bg-emerald-500',
|
||||
'teal' => 'text-white dark:text-white bg-teal-500 dark:bg-teal-600 [&:is(button)]:hover:bg-teal-600 dark:[button]:hover:bg-teal-500',
|
||||
'cyan' => 'text-white dark:text-white bg-cyan-500 dark:bg-cyan-600 [&:is(button)]:hover:bg-cyan-600 dark:[button]:hover:bg-cyan-500',
|
||||
'sky' => 'text-white dark:text-white bg-sky-500 dark:bg-sky-600 [&:is(button)]:hover:bg-sky-600 dark:[button]:hover:bg-sky-500',
|
||||
'blue' => 'text-white dark:text-white bg-blue-500 dark:bg-blue-600 [&:is(button)]:hover:bg-blue-600 dark:[button]:hover:bg-blue-500',
|
||||
'indigo' => 'text-white dark:text-white bg-indigo-500 dark:bg-indigo-600 [&:is(button)]:hover:bg-indigo-600 dark:[button]:hover:bg-indigo-500',
|
||||
'violet' => 'text-white dark:text-white bg-violet-500 dark:bg-violet-600 [&:is(button)]:hover:bg-violet-600 dark:[button]:hover:bg-violet-500',
|
||||
'purple' => 'text-white dark:text-white bg-purple-500 dark:bg-purple-600 [&:is(button)]:hover:bg-purple-600 dark:[button]:hover:bg-purple-500',
|
||||
'fuchsia' => 'text-white dark:text-white bg-fuchsia-500 dark:bg-fuchsia-600 [&:is(button)]:hover:bg-fuchsia-600 dark:[button]:hover:bg-fuchsia-500',
|
||||
'pink' => 'text-white dark:text-white bg-pink-500 dark:bg-pink-600 [&:is(button)]:hover:bg-pink-600 dark:[button]:hover:bg-pink-500',
|
||||
'rose' => 'text-white dark:text-white bg-rose-500 dark:bg-rose-600 [&:is(button)]:hover:bg-rose-600 dark:[button]:hover:bg-rose-500',
|
||||
} : match ($color) {
|
||||
default => 'text-text-secondary [&_button]:text-text-secondary! bg-bg-elevated [&:is(button)]:hover:bg-bg-surface',
|
||||
'red' => 'text-red-700 [&_button]:text-red-700! dark:text-red-200 dark:[&_button]:text-red-200! bg-red-400/20 dark:bg-red-400/40 [&:is(button)]:hover:bg-red-400/30 dark:[button]:hover:bg-red-400/50',
|
||||
'orange' => 'text-orange-700 [&_button]:text-orange-700! dark:text-orange-200 dark:[&_button]:text-orange-200! bg-orange-400/20 dark:bg-orange-400/40 [&:is(button)]:hover:bg-orange-400/30 dark:[button]:hover:bg-orange-400/50',
|
||||
'amber' => 'text-amber-700 [&_button]:text-amber-700! dark:text-amber-200 dark:[&_button]:text-amber-200! bg-amber-400/25 dark:bg-amber-400/40 [&:is(button)]:hover:bg-amber-400/40 dark:[button]:hover:bg-amber-400/50',
|
||||
'yellow' => 'text-yellow-800 [&_button]:text-yellow-800! dark:text-yellow-200 dark:[&_button]:text-yellow-200! bg-yellow-400/25 dark:bg-yellow-400/40 [&:is(button)]:hover:bg-yellow-400/40 dark:[button]:hover:bg-yellow-400/50',
|
||||
'lime' => 'text-lime-800 [&_button]:text-lime-800! dark:text-lime-200 dark:[&_button]:text-lime-200! bg-lime-400/25 dark:bg-lime-400/40 [&:is(button)]:hover:bg-lime-400/35 dark:[button]:hover:bg-lime-400/50',
|
||||
'green' => 'text-green-800 [&_button]:text-green-800! dark:text-green-200 dark:[&_button]:text-green-200! bg-green-400/20 dark:bg-green-400/40 [&:is(button)]:hover:bg-green-400/30 dark:[button]:hover:bg-green-400/50',
|
||||
'emerald' => 'text-emerald-800 [&_button]:text-emerald-800! dark:text-emerald-200 dark:[&_button]:text-emerald-200! bg-emerald-400/20 dark:bg-emerald-400/40 [&:is(button)]:hover:bg-emerald-400/30 dark:[button]:hover:bg-emerald-400/50',
|
||||
'teal' => 'text-teal-800 [&_button]:text-teal-800! dark:text-teal-200 dark:[&_button]:text-teal-200! bg-teal-400/20 dark:bg-teal-400/40 [&:is(button)]:hover:bg-teal-400/30 dark:[button]:hover:bg-teal-400/50',
|
||||
'cyan' => 'text-cyan-800 [&_button]:text-cyan-800! dark:text-cyan-200 dark:[&_button]:text-cyan-200! bg-cyan-400/20 dark:bg-cyan-400/40 [&:is(button)]:hover:bg-cyan-400/30 dark:[button]:hover:bg-cyan-400/50',
|
||||
'sky' => 'text-sky-800 [&_button]:text-sky-800! dark:text-sky-200 dark:[&_button]:text-sky-200! bg-sky-400/20 dark:bg-sky-400/40 [&:is(button)]:hover:bg-sky-400/30 dark:[button]:hover:bg-sky-400/50',
|
||||
'blue' => 'text-blue-800 [&_button]:text-blue-800! dark:text-blue-200 dark:[&_button]:text-blue-200! bg-blue-400/20 dark:bg-blue-400/40 [&:is(button)]:hover:bg-blue-400/30 dark:[button]:hover:bg-blue-400/50',
|
||||
'indigo' => 'text-indigo-700 [&_button]:text-indigo-700! dark:text-indigo-200 dark:[&_button]:text-indigo-200! bg-indigo-400/20 dark:bg-indigo-400/40 [&:is(button)]:hover:bg-indigo-400/30 dark:[button]:hover:bg-indigo-400/50',
|
||||
'violet' => 'text-violet-700 [&_button]:text-violet-700! dark:text-violet-200 dark:[&_button]:text-violet-200! bg-violet-400/20 dark:bg-violet-400/40 [&:is(button)]:hover:bg-violet-400/30 dark:[button]:hover:bg-violet-400/50',
|
||||
'purple' => 'text-purple-700 [&_button]:text-purple-700! dark:text-purple-200 dark:[&_button]:text-purple-200! bg-purple-400/20 dark:bg-purple-400/40 [&:is(button)]:hover:bg-purple-400/30 dark:[button]:hover:bg-purple-400/50',
|
||||
'fuchsia' => 'text-fuchsia-700 [&_button]:text-fuchsia-700! dark:text-fuchsia-200 dark:[&_button]:text-fuchsia-200! bg-fuchsia-400/20 dark:bg-fuchsia-400/40 [&:is(button)]:hover:bg-fuchsia-400/30 dark:[button]:hover:bg-fuchsia-400/50',
|
||||
'pink' => 'text-pink-700 [&_button]:text-pink-700! dark:text-pink-200 dark:[&_button]:text-pink-200! bg-pink-400/20 dark:bg-pink-400/40 [&:is(button)]:hover:bg-pink-400/30 dark:[button]:hover:bg-pink-400/50',
|
||||
'rose' => 'text-rose-700 [&_button]:text-rose-700! dark:text-rose-200 dark:[&_button]:text-rose-200! bg-rose-400/20 dark:bg-rose-400/40 [&:is(button)]:hover:bg-rose-400/30 dark:[button]:hover:bg-rose-400/50',
|
||||
});
|
||||
@endphp
|
||||
|
||||
<flux:button-or-div :attributes="$attributes->class($classes)" data-flux-badge>
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<flux:icon :$icon :variant="$iconVariant" :class="$iconClasses" data-flux-badge-icon />
|
||||
<?php else: ?>
|
||||
{{ $icon }}
|
||||
<?php endif; ?>
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
<?php if ($iconTrailing): ?>
|
||||
<div class="ps-1 flex items-center" data-flux-badge-icon:trailing>
|
||||
<?php if (is_string($iconTrailing)): ?>
|
||||
<flux:icon :icon="$iconTrailing" :variant="$iconVariant" :class="$iconClasses" />
|
||||
<?php else: ?>
|
||||
{{ $iconTrailing }}
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</flux:button-or-div>
|
||||
63
resources/views/flux/brand.blade.php
Normal file
63
resources/views/flux/brand.blade.php
Normal file
@@ -0,0 +1,63 @@
|
||||
@blaze
|
||||
|
||||
@php $logoDark ??= $attributes->pluck('logo:dark'); @endphp
|
||||
|
||||
@props([
|
||||
'name' => null,
|
||||
'logo' => null,
|
||||
'logoDark' => null,
|
||||
'alt' => null,
|
||||
'href' => '/',
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('h-10 flex items-center me-4')
|
||||
;
|
||||
|
||||
$textClasses = Flux::classes()
|
||||
->add('text-sm font-medium truncate [:where(&)]:text-zinc-800 dark:[:where(&)]:text-zinc-100')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<?php if ($name): ?>
|
||||
<a href="{{ $href }}" {{ $attributes->class([ $classes, 'gap-2' ]) }} data-flux-brand>
|
||||
<?php if ($logo instanceof \Illuminate\View\ComponentSlot): ?>
|
||||
<div {{ $logo->attributes->class('flex items-center justify-center [:where(&)]:h-6 [:where(&)]:min-w-6 [:where(&)]:rounded-sm overflow-hidden shrink-0') }}>
|
||||
{{ $logo }}
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="flex items-center justify-center h-6 rounded-sm overflow-hidden shrink-0">
|
||||
<?php if ($logoDark): ?>
|
||||
<img src="{{ $logo }}" alt="{{ $alt }}" class="h-6 dark:hidden" />
|
||||
<img src="{{ $logoDark }}" alt="{{ $alt }}" class="h-6 hidden dark:block" />
|
||||
<?php elseif ($logo): ?>
|
||||
<img src="{{ $logo }}" alt="{{ $alt }}" class="h-6" />
|
||||
<?php else: ?>
|
||||
{{ $slot }}
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="{{ $textClasses }}">{{ $name }}</div>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<a href="{{ $href }}" {{ $attributes->class($classes) }} data-flux-brand>
|
||||
<?php if ($logo instanceof \Illuminate\View\ComponentSlot): ?>
|
||||
<div {{ $logo->attributes->class('flex items-center justify-center [:where(&)]:h-6 [:where(&)]:min-w-6 [:where(&)]:rounded-sm overflow-hidden shrink-0') }}>
|
||||
{{ $logo }}
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="flex items-center justify-center h-6 rounded-sm overflow-hidden shrink-0">
|
||||
<?php if ($logoDark): ?>
|
||||
<img src="{{ $logo }}" alt="{{ $alt }}" class="h-6 dark:hidden" />
|
||||
<img src="{{ $logoDark }}" alt="{{ $alt }}" class="h-6 hidden dark:block" />
|
||||
<?php elseif ($logo): ?>
|
||||
<img src="{{ $logo }}" alt="{{ $alt }}" class="h-6" />
|
||||
<?php else: ?>
|
||||
{{ $slot }}
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
5
resources/views/flux/breadcrumbs/index.blade.php
Normal file
5
resources/views/flux/breadcrumbs/index.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@blaze
|
||||
|
||||
<div {{ $attributes->class('flex') }} data-flux-breadcrumbs>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
69
resources/views/flux/breadcrumbs/item.blade.php
Normal file
69
resources/views/flux/breadcrumbs/item.blade.php
Normal file
@@ -0,0 +1,69 @@
|
||||
@blaze
|
||||
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'separator' => null,
|
||||
'iconVariant' => 'mini',
|
||||
'icon' => null,
|
||||
'href' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('flex items-center')
|
||||
->add('text-sm font-medium')
|
||||
->add('group/breadcrumb')
|
||||
;
|
||||
|
||||
$linkClasses = Flux::classes()
|
||||
->add('text-zinc-800 dark:text-white')
|
||||
->add('hover:underline decoration-zinc-800/20 underline-offset-4');
|
||||
|
||||
$staticTextClasses = Flux::classes()
|
||||
->add('text-gray-500 dark:text-white/80')
|
||||
;
|
||||
|
||||
$separatorClasses = Flux::classes()
|
||||
->add('mx-1 text-zinc-300 dark:text-white/80')
|
||||
->add('group-last/breadcrumb:hidden')
|
||||
;
|
||||
|
||||
$iconClasses = Flux::classes()
|
||||
// When using the outline icon variant, we need to size it down to match the default icon sizes...
|
||||
->add($iconVariant === 'outline' ? 'size-5' : '')
|
||||
;
|
||||
|
||||
[ $styleAttributes, $attributes ] = Flux::splitAttributes($attributes);
|
||||
@endphp
|
||||
|
||||
<div {{ $styleAttributes->class($classes) }} data-flux-breadcrumbs-item>
|
||||
<?php if ($href): ?>
|
||||
<a {{ $attributes->class($linkClasses) }} href="{{ $href }}">
|
||||
<?php if ($icon): ?>
|
||||
<flux:icon :$icon :variant="$iconVariant" class="{{ $iconClasses }}" />
|
||||
<?php else: ?>
|
||||
{{ $slot }}
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<div {{ $attributes->class($staticTextClasses) }}>
|
||||
<?php if ($icon): ?>
|
||||
<flux:icon :$icon :variant="$iconVariant" class="{{ $iconClasses }}" />
|
||||
<?php else: ?>
|
||||
{{ $slot }}
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
@if ($separator == null)
|
||||
<flux:icon icon="chevron-right" variant="mini" class="{{ $separatorClasses->add('rtl:hidden') }}" />
|
||||
<flux:icon icon="chevron-left" variant="mini" class="{{ $separatorClasses->add('hidden rtl:inline') }}" />
|
||||
@elseif (! is_string($separator))
|
||||
{{ $separator }}
|
||||
@elseif ($separator === 'slash')
|
||||
<flux:icon icon="slash" variant="mini" class="{{ $separatorClasses->add('rtl:-scale-x-100') }}" />
|
||||
@else
|
||||
<flux:icon :icon="$separator" variant="mini" class="{{ $separatorClasses }}" />
|
||||
@endif
|
||||
</div>
|
||||
47
resources/views/flux/button/group.blade.php
Normal file
47
resources/views/flux/button/group.blade.php
Normal file
@@ -0,0 +1,47 @@
|
||||
@blaze
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('flex group/button')
|
||||
->add([
|
||||
// With the external borders, let's always make sure the first and last children have outside borders.
|
||||
// For internal borders, we will ensure that all left borders are removed, but the right borders remain.
|
||||
// But when there is a input groupsuffix, then there should be no right internal border.
|
||||
// That way we shouldn't ever have a double border...
|
||||
|
||||
// All inputs borders...
|
||||
'[&>[data-flux-input]:last-child:not(:first-child)>[data-flux-group-target]:not([data-invalid])]:border-s-0',
|
||||
'[&>[data-flux-input]:not(:first-child):not(:last-child)>[data-flux-group-target]:not([data-invalid])]:border-s-0',
|
||||
'[&>[data-flux-input]:has(+[data-flux-input-group-suffix])>[data-flux-group-target]:not([data-invalid])]:border-e-0',
|
||||
|
||||
// Selects and date pickers borders...
|
||||
'[&>*:last-child:not(:first-child)>[data-flux-group-target]:not([data-invalid])]:border-s-0',
|
||||
'[&>*:not(:first-child):not(:last-child)>[data-flux-group-target]:not([data-invalid])]:border-s-0',
|
||||
'[&>*:has(+[data-flux-input-group-suffix])>[data-flux-group-target]:not([data-invalid])]:border-e-0',
|
||||
|
||||
// Buttons borders...
|
||||
'[&>[data-flux-group-target]:last-child:not(:first-child)]:border-s-0',
|
||||
'[&>[data-flux-group-target]:not(:first-child):not(:last-child)]:border-s-0',
|
||||
'[&>[data-flux-group-target]:has(+[data-flux-input-group-suffix])]:border-e-0',
|
||||
|
||||
// "Weld" the borders of inputs together by overriding their border radiuses...
|
||||
'[&>[data-flux-group-target]:not(:first-child):not(:last-child)]:rounded-none',
|
||||
'[&>[data-flux-group-target]:first-child:not(:last-child)]:rounded-e-none',
|
||||
'[&>[data-flux-group-target]:last-child:not(:first-child)]:rounded-s-none',
|
||||
|
||||
// "Weld" borders for sub-children of group targets (button element inside ui-select element, etc.)...
|
||||
'[&>*:not(:first-child):not(:last-child):not(:only-child)>[data-flux-group-target]]:rounded-none',
|
||||
'[&>*:first-child:not(:last-child)>[data-flux-group-target]]:rounded-e-none',
|
||||
'[&>*:last-child:not(:first-child)>[data-flux-group-target]]:rounded-s-none',
|
||||
|
||||
// "Weld" borders for sub-sub-children of group targets (input element inside div inside ui-select element (combobox))...
|
||||
'[&>*:not(:first-child):not(:last-child):not(:only-child)>[data-flux-input]>[data-flux-group-target]]:rounded-none',
|
||||
'[&>*:first-child:not(:last-child)>[data-flux-input]>[data-flux-group-target]]:rounded-e-none',
|
||||
'[&>*:last-child:not(:first-child)>[data-flux-input]>[data-flux-group-target]]:rounded-s-none',
|
||||
])
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }} data-flux-button-group>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
202
resources/views/flux/button/index.blade.php
Normal file
202
resources/views/flux/button/index.blade.php
Normal file
@@ -0,0 +1,202 @@
|
||||
@blaze
|
||||
|
||||
@php $iconTrailing ??= $attributes->pluck('icon:trailing'); @endphp
|
||||
@php $iconLeading ??= $attributes->pluck('icon:leading'); @endphp
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'iconTrailing' => null,
|
||||
'variant' => 'outline',
|
||||
'iconVariant' => null,
|
||||
'iconLeading' => null,
|
||||
'type' => 'button',
|
||||
'loading' => null,
|
||||
'align' => 'center',
|
||||
'size' => 'base',
|
||||
'square' => null,
|
||||
'color' => null,
|
||||
'inset' => null,
|
||||
'icon' => null,
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$iconLeading = $icon ??= $iconLeading;
|
||||
|
||||
// Button should be a square if it has no text contents...
|
||||
$square ??= $slot->isEmpty();
|
||||
|
||||
// Size-up icons in square/icon-only buttons... (xs buttons just get micro size/style...)
|
||||
$iconVariant ??= ($size === 'xs')
|
||||
? ($square ? 'micro' : 'micro')
|
||||
: ($square ? 'mini' : 'micro');
|
||||
|
||||
$iconTrailingVariant ??= $attributes->pluck('icon-trailing:variant', $iconVariant);
|
||||
|
||||
// When using the outline icon variant, we need to size it down to match the default icon sizes...
|
||||
$iconClasses = Flux::classes()
|
||||
->add($iconVariant === 'outline' ? ($square && $size !== 'xs' ? 'size-5' : 'size-4') : '')
|
||||
->add($attributes->pluck('icon:class'))
|
||||
;
|
||||
|
||||
$iconTrailingClasses = Flux::classes()
|
||||
->add($iconTrailingVariant === 'outline' ? ($square && $size !== 'xs' ? 'size-5' : 'size-4') : '')
|
||||
->add($attributes->pluck('icon-trailing:class'))
|
||||
;
|
||||
|
||||
$isTypeSubmitAndNotDisabledOnRender = $type === 'submit' && ! $attributes->has('disabled');
|
||||
|
||||
$isJsMethod = str_starts_with($attributes->whereStartsWith('wire:click')->first() ?? '', '$js.');
|
||||
|
||||
$loading ??= $loading ?? ($isTypeSubmitAndNotDisabledOnRender || $attributes->whereStartsWith('wire:click')->isNotEmpty() && ! $isJsMethod);
|
||||
|
||||
if ($loading && $type !== 'submit' && ! $isJsMethod) {
|
||||
$attributes = $attributes->merge(['wire:loading.attr' => 'data-flux-loading']);
|
||||
|
||||
// We need to add `wire:target` here because without it the loading indicator won't be scoped
|
||||
// by method params, causing multiple buttons with the same method but different params to
|
||||
// trigger each other's loading indicators...
|
||||
if (! $attributes->has('wire:target') && $target = $attributes->whereStartsWith('wire:click')->first()) {
|
||||
$attributes = $attributes->merge(['wire:target' => $target], escape: false);
|
||||
}
|
||||
}
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('relative items-center font-medium justify-center gap-2 whitespace-nowrap')
|
||||
->add('disabled:opacity-75 dark:disabled:opacity-75 disabled:cursor-default disabled:pointer-events-none')
|
||||
->add(match ($align) {
|
||||
'start' => 'justify-start',
|
||||
'center' => 'justify-center',
|
||||
'end' => 'justify-end',
|
||||
})
|
||||
->add(match ($size) { // Size...
|
||||
'base' => 'h-10 text-sm rounded-lg' . ' ' . (
|
||||
$square
|
||||
? 'w-10'
|
||||
// If we have an icon, we want to reduce the padding on the side that has the icon...
|
||||
: ($iconLeading && $iconLeading !== '' ? 'ps-3' : 'ps-4') . ' ' . ($iconTrailing && $iconTrailing !== '' ? 'pe-3' : 'pe-4')
|
||||
),
|
||||
'sm' => 'h-8 text-sm rounded-md' . ' ' . ($square ? 'w-8' : 'px-3'),
|
||||
'xs' => 'h-6 text-xs rounded-md' . ' ' . ($square ? 'w-6' : 'px-2'),
|
||||
})
|
||||
->add('inline-flex') // Buttons are inline by default but links are blocks, so inline-flex is needed here to ensure link-buttons are displayed the same as buttons...
|
||||
->add($inset ? match ($size) { // Inset...
|
||||
'base' => $square
|
||||
? Flux::applyInset($inset, top: '-mt-2.5', right: '-me-2.5', bottom: '-mb-2.5', left: '-ms-2.5')
|
||||
: Flux::applyInset($inset, top: '-mt-2.5', right: '-me-4', bottom: '-mb-3', left: '-ms-4'),
|
||||
'sm' => $square
|
||||
? Flux::applyInset($inset, top: '-mt-1.5', right: '-me-1.5', bottom: '-mb-1.5', left: '-ms-1.5')
|
||||
: Flux::applyInset($inset, top: '-mt-1.5', right: '-me-3', bottom: '-mb-1.5', left: '-ms-3'),
|
||||
'xs' => $square
|
||||
? Flux::applyInset($inset, top: '-mt-1', right: '-me-1', bottom: '-mb-1', left: '-ms-1')
|
||||
: Flux::applyInset($inset, top: '-mt-1', right: '-me-2', bottom: '-mb-1', left: '-ms-2'),
|
||||
} : '')
|
||||
->add(match ($variant) { // Background color...
|
||||
'primary' => $color ? 'bg-accent hover:bg-accent/90' : 'bg-orange-primary hover:bg-orange-light',
|
||||
'filled' => 'bg-bg-elevated hover:bg-bg-surface',
|
||||
'outline' => 'bg-transparent hover:bg-bg-elevated',
|
||||
'danger' => 'bg-red-500 hover:bg-red-600',
|
||||
'ghost' => 'bg-transparent hover:bg-bg-elevated',
|
||||
'subtle' => 'bg-transparent hover:bg-bg-elevated',
|
||||
})
|
||||
->add(match ($variant) { // Text color...
|
||||
'primary' => $color ? 'text-accent-foreground' : 'text-text-primary',
|
||||
'filled' => 'text-text-primary',
|
||||
'outline' => 'text-text-secondary hover:text-text-primary',
|
||||
'danger' => 'text-white',
|
||||
'ghost' => 'text-text-secondary hover:text-text-primary',
|
||||
'subtle' => 'text-text-tertiary hover:text-text-primary',
|
||||
})
|
||||
->add(match ($variant) { // Border color...
|
||||
'primary' => 'border-0',
|
||||
'outline' => 'border border-border-default hover:border-border-default',
|
||||
default => '',
|
||||
})
|
||||
->add(match ($variant) { // Shadows...
|
||||
'primary' => '',
|
||||
'danger' => '',
|
||||
'outline' => '',
|
||||
default => '',
|
||||
})
|
||||
->add(match ($variant) { // Grouped border treatments...
|
||||
'ghost' => '',
|
||||
'subtle' => '',
|
||||
'outline' => '[[data-flux-button-group]_&]:border-s-0 [:is([data-flux-button-group]>&:first-child,_[data-flux-button-group]_:first-child>&)]:border-s-[1px]',
|
||||
'filled' => '[[data-flux-button-group]_&]:border-e [:is([data-flux-button-group]>&:last-child,_[data-flux-button-group]_:last-child>&)]:border-e-0 [[data-flux-button-group]_&]:border-zinc-200/80 dark:[[data-flux-button-group]_&]:border-zinc-900/50',
|
||||
'danger' => '[[data-flux-button-group]_&]:border-e [:is([data-flux-button-group]>&:last-child,_[data-flux-button-group]_:last-child>&)]:border-e-0 [[data-flux-button-group]_&]:border-red-600 dark:[[data-flux-button-group]_&]:border-red-900/25',
|
||||
'primary' => '[[data-flux-button-group]_&]:border-e-0 [:is([data-flux-button-group]>&:last-child,_[data-flux-button-group]_:last-child>&)]:border-e-[1px] dark:[:is([data-flux-button-group]>&:last-child,_[data-flux-button-group]_:last-child>&)]:border-e-0 dark:[:is([data-flux-button-group]>&:last-child,_[data-flux-button-group]_:last-child>&)]:border-s-[1px] [:is([data-flux-button-group]>&:not(:first-child),_[data-flux-button-group]_:not(:first-child)>&)]:border-s-[color-mix(in_srgb,var(--color-accent-foreground),transparent_85%)]',
|
||||
})
|
||||
->add($loading ? [ // Loading states...
|
||||
'*:transition-opacity',
|
||||
$type === 'submit' ? '[&[disabled]>:not([data-flux-loading-indicator])]:opacity-0' : '[&[data-loading]>:not([data-flux-loading-indicator])]:opacity-0 [&[data-flux-loading]>:not([data-flux-loading-indicator])]:opacity-0',
|
||||
$type === 'submit' ? '[&[disabled]>[data-flux-loading-indicator]]:opacity-100' : '[&[data-loading]>[data-flux-loading-indicator]]:opacity-100 [&[data-flux-loading]>[data-flux-loading-indicator]]:opacity-100',
|
||||
$type === 'submit' ? '[&[disabled]]:pointer-events-none' : 'data-loading:pointer-events-none data-flux-loading:pointer-events-none',
|
||||
] : [])
|
||||
->add($variant === 'primary' ? match ($color) {
|
||||
'slate' => '[--color-accent:var(--color-slate-800)] [--color-accent-content:var(--color-slate-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-slate-800)]',
|
||||
'gray' => '[--color-accent:var(--color-gray-800)] [--color-accent-content:var(--color-gray-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-gray-800)]',
|
||||
'zinc' => '[--color-accent:var(--color-zinc-800)] [--color-accent-content:var(--color-zinc-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-zinc-800)]',
|
||||
'neutral' => '[--color-accent:var(--color-neutral-800)] [--color-accent-content:var(--color-neutral-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-neutral-800)]',
|
||||
'stone' => '[--color-accent:var(--color-stone-800)] [--color-accent-content:var(--color-stone-800)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-white)] dark:[--color-accent-content:var(--color-white)] dark:[--color-accent-foreground:var(--color-stone-800)]',
|
||||
'red' => '[--color-accent:var(--color-red-500)] [--color-accent-content:var(--color-red-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-red-500)] dark:[--color-accent-content:var(--color-red-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'orange' => '[--color-accent:var(--color-orange-500)] [--color-accent-content:var(--color-orange-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-orange-400)] dark:[--color-accent-content:var(--color-orange-400)] dark:[--color-accent-foreground:var(--color-orange-950)]',
|
||||
'amber' => '[--color-accent:var(--color-amber-400)] [--color-accent-content:var(--color-amber-600)] [--color-accent-foreground:var(--color-amber-950)] dark:[--color-accent:var(--color-amber-400)] dark:[--color-accent-content:var(--color-amber-400)] dark:[--color-accent-foreground:var(--color-amber-950)]',
|
||||
'yellow' => '[--color-accent:var(--color-yellow-400)] [--color-accent-content:var(--color-yellow-600)] [--color-accent-foreground:var(--color-yellow-950)] dark:[--color-accent:var(--color-yellow-400)] dark:[--color-accent-content:var(--color-yellow-400)] dark:[--color-accent-foreground:var(--color-yellow-950)]',
|
||||
'lime' => '[--color-accent:var(--color-lime-400)] [--color-accent-content:var(--color-lime-600)] [--color-accent-foreground:var(--color-lime-900)] dark:[--color-accent:var(--color-lime-400)] dark:[--color-accent-content:var(--color-lime-400)] dark:[--color-accent-foreground:var(--color-lime-950)]',
|
||||
'green' => '[--color-accent:var(--color-green-600)] [--color-accent-content:var(--color-green-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-green-600)] dark:[--color-accent-content:var(--color-green-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'emerald' => '[--color-accent:var(--color-emerald-600)] [--color-accent-content:var(--color-emerald-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-emerald-600)] dark:[--color-accent-content:var(--color-emerald-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'teal' => '[--color-accent:var(--color-teal-600)] [--color-accent-content:var(--color-teal-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-teal-600)] dark:[--color-accent-content:var(--color-teal-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'cyan' => '[--color-accent:var(--color-cyan-600)] [--color-accent-content:var(--color-cyan-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-cyan-600)] dark:[--color-accent-content:var(--color-cyan-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'sky' => '[--color-accent:var(--color-sky-600)] [--color-accent-content:var(--color-sky-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-sky-600)] dark:[--color-accent-content:var(--color-sky-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'blue' => '[--color-accent:var(--color-blue-500)] [--color-accent-content:var(--color-blue-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-blue-500)] dark:[--color-accent-content:var(--color-blue-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'indigo' => '[--color-accent:var(--color-indigo-500)] [--color-accent-content:var(--color-indigo-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-indigo-500)] dark:[--color-accent-content:var(--color-indigo-300)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'violet' => '[--color-accent:var(--color-violet-500)] [--color-accent-content:var(--color-violet-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-violet-500)] dark:[--color-accent-content:var(--color-violet-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'purple' => '[--color-accent:var(--color-purple-500)] [--color-accent-content:var(--color-purple-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-purple-500)] dark:[--color-accent-content:var(--color-purple-300)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'fuchsia' => '[--color-accent:var(--color-fuchsia-600)] [--color-accent-content:var(--color-fuchsia-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-fuchsia-600)] dark:[--color-accent-content:var(--color-fuchsia-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'pink' => '[--color-accent:var(--color-pink-600)] [--color-accent-content:var(--color-pink-600)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-pink-600)] dark:[--color-accent-content:var(--color-pink-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
'rose' => '[--color-accent:var(--color-rose-500)] [--color-accent-content:var(--color-rose-500)] [--color-accent-foreground:var(--color-white)] dark:[--color-accent:var(--color-rose-500)] dark:[--color-accent-content:var(--color-rose-400)] dark:[--color-accent-foreground:var(--color-white)]',
|
||||
default => '',
|
||||
} : '')
|
||||
;
|
||||
|
||||
// Exempt subtle and ghost buttons from receiving border roundness overrides from button.group...
|
||||
$attributes = $attributes->merge([
|
||||
'data-flux-group-target' => ! in_array($variant, ['subtle', 'ghost']),
|
||||
]);
|
||||
@endphp
|
||||
|
||||
<flux:with-tooltip :$attributes>
|
||||
<flux:button-or-link-pure :$type :attributes="$attributes->class($classes)" data-flux-button>
|
||||
<?php if ($loading): ?>
|
||||
<div class="absolute inset-0 flex items-center justify-center opacity-0" data-flux-loading-indicator>
|
||||
<flux:icon icon="loading" :variant="$iconVariant" :class="$iconClasses" />
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (is_string($iconLeading) && $iconLeading !== ''): ?>
|
||||
<flux:icon :icon="$iconLeading" :variant="$iconVariant" :class="$iconClasses" />
|
||||
<?php elseif ($iconLeading): ?>
|
||||
{{ $iconLeading }}
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (($loading || $iconLeading || $iconTrailing) && ! $slot->isEmpty()): ?>
|
||||
{{-- If we have a loading indicator, we need to wrap it in a span so it can be a target of *:opacity-0... --}}
|
||||
{{-- Also, if we have an icon, we need to wrap it in a span so it can be recognized as a child of the button for :first-child selectors... --}}
|
||||
<span>{{ $slot }}</span>
|
||||
<?php else: ?>
|
||||
{{ $slot }}
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($kbd): ?>
|
||||
<div class="text-xs text-zinc-400 dark:text-zinc-400">{{ $kbd }}</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (is_string($iconTrailing) && $iconTrailing !== ''): ?>
|
||||
{{-- Adding the extra margin class inline on the icon component below was causing a double up, so it needs to be added here first... --}}
|
||||
<?php $iconClasses->add($square ? '' : '-ms-1'); ?>
|
||||
<flux:icon :icon="$iconTrailing" :variant="$iconTrailingVariant" :class="$iconTrailingClasses" />
|
||||
<?php elseif ($iconTrailing): ?>
|
||||
{{ $iconTrailing }}
|
||||
<?php endif; ?>
|
||||
</flux:button-or-link-pure>
|
||||
</flux:with-tooltip>
|
||||
222
resources/views/flux/calendar/index.blade.php
Normal file
222
resources/views/flux/calendar/index.blade.php
Normal file
@@ -0,0 +1,222 @@
|
||||
@props([
|
||||
'selectableHeader' => null,
|
||||
'weekNumbers' => null,
|
||||
'unavailable' => null,
|
||||
'withInputs' => null,
|
||||
'navigation' => null,
|
||||
'withToday' => null,
|
||||
'months' => null,
|
||||
'value' => null,
|
||||
'mode' => null,
|
||||
'size' => null,
|
||||
'name' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
// We only want to show the name attribute if it has been set manually
|
||||
// but not if it has been set from the `wire:model` attribute...
|
||||
$showName = isset($name);
|
||||
|
||||
if (! isset($name)) {
|
||||
$name = $attributes->whereStartsWith('wire:model')->first();
|
||||
}
|
||||
|
||||
// Support adding the .self modifier to the wire:model directive...
|
||||
if (($wireModel = $attributes->wire('model')) && $wireModel->directive && ! $wireModel->hasModifier('self')) {
|
||||
unset($attributes[$wireModel->directive]);
|
||||
|
||||
$wireModel->directive .= '.self';
|
||||
|
||||
$attributes = $attributes->merge([$wireModel->directive => $wireModel->value]);
|
||||
}
|
||||
|
||||
$months = $months ?? ($mode === 'range' ? 2 : 1);
|
||||
|
||||
$range = $mode === 'range';
|
||||
|
||||
// Mark it invalid if the property or any of it's nested attributes have errors...
|
||||
$invalid ??= ($name && ($errors->has($name) || $errors->has($name . '.*')));
|
||||
|
||||
$class = Flux::classes()
|
||||
->add('isolate relative')
|
||||
;
|
||||
|
||||
$sizeClasses = match ($size) {
|
||||
'2xl' => $weekNumbers ? 'size-12 sm:size-16' : 'size-13 sm:size-16',
|
||||
'xl' => $weekNumbers ? 'size-11 sm:size-14' : 'size-12 sm:size-14',
|
||||
'lg' => $weekNumbers ? 'size-10 sm:size-12' : 'size-11 sm:size-12',
|
||||
default => $weekNumbers ? 'size-10 sm:size-11' : 'size-11 sm:size-11',
|
||||
'sm' => $weekNumbers ? 'size-9 sm:size-10' : 'size-11 sm:size-10',
|
||||
'xs' => $weekNumbers ? 'size-8 sm:size-9' : 'size-10 sm:size-9',
|
||||
};
|
||||
|
||||
// Add support for `$value` being an array, if for example it's coming from
|
||||
// the `old()` helper or if a user prefers to pass data in as an array...
|
||||
if (is_array($value)) {
|
||||
$value = match (true) {
|
||||
$mode === 'range' => isset($value['start']) && isset($value['end']) ? $value['start'] . '/' . $value['end'] : null,
|
||||
default => collect($value)->join(','),
|
||||
};
|
||||
}
|
||||
|
||||
if (isset($unavailable)) {
|
||||
$unavailable = collect($unavailable)->implode(',');
|
||||
}
|
||||
@endphp
|
||||
|
||||
<ui-calendar
|
||||
wire:ignore.children
|
||||
{{ $attributes->class($class) }}
|
||||
data-flux-calendar
|
||||
@if ($mode) mode="{{ $mode }}" @endif
|
||||
months="1"
|
||||
sm:months="{{ $months }}"
|
||||
@if (isset($unavailable) && $unavailable !== '') unavailable="{{ $unavailable }}" @endif
|
||||
@if ($showName) name="{{ $name }}" @endif
|
||||
@if (isset($value)) value="{{ $value }}" @endif
|
||||
>
|
||||
<?php if ($withInputs): ?>
|
||||
<ui-calendar-inputs class="flex items-center p-2 border-b border-zinc-200 dark:border-white/10">
|
||||
<?php if ($range): ?>
|
||||
<div class="sm:px-2 flex items-center gap-4">
|
||||
<div class="flex items-center gap-2"><span class="max-sm:hidden text-sm font-medium text-zinc-800 dark:text-white">{{ __('Start') }}</span> <flux:input type="date" class="w-[full] sm:w-[11.25rem]" /></div>
|
||||
<div class="flex items-center gap-2"><span class="max-sm:hidden text-sm font-medium text-zinc-800 dark:text-white">{{ __('End') }}</span> <flux:input type="date" class="w-[full] sm:w-[11.25rem]" /></div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<flux:input type="date" class="w-full sm:w-[11.25rem]" />
|
||||
<?php endif; ?>
|
||||
</ui-calendar-inputs>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="relative">
|
||||
<div class="z-10 absolute top-0 inset-x-0 p-2">
|
||||
<header class="flex justify-between items-center">
|
||||
<div class="flex items-center gap-2">
|
||||
<?php if ($selectableHeader): ?>
|
||||
<ui-calendar-month display="short" class="font-medium text-sm text-zinc-800 dark:text-white">
|
||||
<select
|
||||
class="h-10 py-0 border-0 text-sm sm:h-8 appearance-none rounded-lg bg-zinc-100 dark:bg-white/10 dark:[&>option]:bg-zinc-700 dark:[&>option]:text-white px-3 sm:ps-2 [background-position:_right_.25rem_center_!important] rtl:[background-position:_left_.25rem_center_!important] pe-[1.35rem] bg-[length:16px_16px] bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%2300000040%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] hover:bg-[length:16px_16px] hover:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%231f2937%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] dark:bg-[length:16px_16px] dark:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%23ffffff75%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] dark:hover:bg-[length:16px_16px] dark:hover:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%23ffffff%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] bg-no-repeat"
|
||||
>
|
||||
<template>
|
||||
<option><slot></slot></option>
|
||||
</template>
|
||||
</select>
|
||||
</ui-calendar-month>
|
||||
|
||||
<ui-calendar-year class="font-medium text-sm text-zinc-800 dark:text-white">
|
||||
<select
|
||||
class="h-10 py-0 border-0 text-sm sm:h-8 appearance-none rounded-lg bg-zinc-100 dark:bg-white/10 dark:[&>option]:bg-zinc-700 dark:[&>option]:text-white px-3 sm:ps-2 [background-position:_right_.25rem_center_!important] rtl:[background-position:_left_.25rem_center_!important] pe-[1.35rem] bg-[length:16px_16px] bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%2300000040%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] hover:bg-[length:16px_16px] hover:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%231f2937%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] dark:bg-[length:16px_16px] dark:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%23ffffff75%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] dark:hover:bg-[length:16px_16px] dark:hover:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%23ffffff%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] bg-no-repeat"
|
||||
>
|
||||
<template>
|
||||
<option><slot></slot></option>
|
||||
</template>
|
||||
</select>
|
||||
</ui-calendar-year>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<?php if ($withToday): ?>
|
||||
<ui-calendar-today class="size-10 sm:size-8 rounded-lg flex items-center justify-center text-zinc-400 hover:bg-zinc-100 hover:text-zinc-800 dark:hover:bg-white/5 dark:hover:text-white [&[disabled]]:opacity-50 [&[disabled]]:pointer-events-none" aria-label="Previous month">
|
||||
<div class="relative">
|
||||
<template name="today">
|
||||
<div class="cursor-default absolute inset-0 mt-[3px] flex items-center justify-center text-[.5625rem] font-semibold"><slot></slot></div>
|
||||
</template>
|
||||
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.75 2C5.94891 2 6.13968 2.07902 6.28033 2.21967C6.42098 2.36032 6.5 2.55109 6.5 2.75V4H13.5V2.75C13.5 2.55109 13.579 2.36032 13.7197 2.21967C13.8603 2.07902 14.0511 2 14.25 2C14.4489 2 14.6397 2.07902 14.7803 2.21967C14.921 2.36032 15 2.55109 15 2.75V4H15.25C15.9793 4 16.6788 4.28973 17.1945 4.80546C17.7103 5.32118 18 6.02065 18 6.75V15.25C18 15.9793 17.7103 16.6788 17.1945 17.1945C16.6788 17.7103 15.9793 18 15.25 18H4.75C4.02065 18 3.32118 17.7103 2.80546 17.1945C2.28973 16.6788 2 15.9793 2 15.25V6.75C2 6.02065 2.28973 5.32118 2.80546 4.80546C3.32118 4.28973 4.02065 4 4.75 4H5V2.75C5 2.55109 5.07902 2.36032 5.21967 2.21967C5.36032 2.07902 5.55109 2 5.75 2ZM4.75 6.5C4.06 6.5 3.5 7.06 3.5 7.75V15.25C3.5 15.94 4.06 16.5 4.75 16.5H15.25C15.94 16.5 16.5 15.94 16.5 15.25V7.75C16.5 7.06 15.94 6.5 15.25 6.5H4.75Z" fill="currentColor"/>
|
||||
</svg>
|
||||
</div>
|
||||
</ui-calendar-today>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($navigation !== false): ?>
|
||||
<ui-calendar-previous class="size-10 sm:size-8 rounded-lg flex items-center justify-center text-zinc-400 hover:bg-zinc-100 hover:text-zinc-800 dark:hover:bg-white/5 dark:hover:text-white [&[disabled]]:opacity-50 [&[disabled]]:pointer-events-none" aria-label="Previous month">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 rtl:hidden"> <path fill-rule="evenodd" d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" /> </svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 hidden rtl:block"> <path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /> </svg>
|
||||
</ui-calendar-previous>
|
||||
|
||||
<ui-calendar-next class="size-10 sm:size-8 rounded-lg flex items-center justify-center text-zinc-400 hover:bg-zinc-100 hover:text-zinc-800 dark:hover:bg-white/5 dark:hover:text-white [&[disabled]]:opacity-50 [&[disabled]]:pointer-events-none [&[disabled]_&]:text-zinc-400" aria-label="Next month">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 rtl:hidden"> <path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /> </svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 hidden rtl:block"> <path fill-rule="evenodd" d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" /> </svg>
|
||||
</ui-calendar-next>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ui-calendar-months class="relative flex justify-center p-2 gap-4">
|
||||
<template name="month">
|
||||
<div>
|
||||
<template name="heading">
|
||||
<div class="@if ($selectableHeader) [[data-month]:first-of-type_&]:opacity-0 @endif mb-2 px-2 h-10 sm:h-8 flex items-center">
|
||||
<div class="font-medium text-sm text-zinc-800 dark:text-white"><slot></slot></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="flex w-full">
|
||||
<?php if ($weekNumbers): ?>
|
||||
<th scope="col" class="{{ $sizeClasses }} text-sm font-medium text-zinc-500 dark:text-zinc-300 flex items-center"><div class="w-full">#</div></th>
|
||||
<?php endif; ?>
|
||||
|
||||
<template name="weekday">
|
||||
<th scope="col" class="{{ $sizeClasses }} text-sm font-medium text-zinc-500 dark:text-zinc-300 flex items-center"><div class="w-full"><slot></slot></div></th>
|
||||
</template>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<template name="week">
|
||||
<tr class="flex w-full not-first-of-type:mt-1 [&:first-of-type_td[data-in-range]:not([data-selected]):first-child]:rounded-s-none [&:last-of-type_td[data-in-range]:not([data-selected]):last-child]:rounded-e-none">
|
||||
<?php if ($weekNumbers): ?>
|
||||
<template name="number">
|
||||
<td class="p-0 relative {{ $sizeClasses }} text-xs font-medium text-zinc-400 flex items-center justify-center">
|
||||
<slot></slot>
|
||||
</td>
|
||||
</template>
|
||||
<?php endif; ?>
|
||||
<template name="day">
|
||||
<?php if ($attributes->has('static')): ?>
|
||||
<td class="p-0 data-unavailable:line-through data-in-range:bg-zinc-100 dark:data-in-range:bg-white/10 data-start:rounded-s-lg data-end:rounded-e-lg data-end-preview:rounded-e-lg first-of-type:rounded-s-lg last-of-type:rounded-e-lg [&[data-selected]+[data-selected]]:rounded-s-none">
|
||||
<div class="relative {{ $sizeClasses }} text-sm font-medium text-zinc-800 dark:text-white flex items-center justify-center rounded-lg [td[data-selected]:has(+td[data-selected])_&]:rounded-e-none [td[data-selected]+td[data-selected]_&]:rounded-s-none [td[data-selected]_&]:bg-[var(--color-accent)] [td[data-selected]_&]:text-[var(--color-accent-foreground)] [td[data-selected]_&[disabled]]:opacity-50 [td[disabled]_&]:text-zinc-400 [td[disabled]_&]:pointer-events-none [td[disabled]_&]:cursor-default">
|
||||
<div class="absolute inset-0 hidden [td[data-today]_&]:flex justify-center items-end"><div class="mb-1 size-1 rounded-full bg-zinc-800 dark:bg-white [td[data-selected]_&]:bg-white dark:[td[data-selected]_&]:bg-zinc-800"></div></div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</td>
|
||||
<?php else: ?>
|
||||
<td class="_max-sm:data-outside:opacity-0 p-0 data-unavailable:line-through data-in-range:bg-zinc-100 dark:data-in-range:bg-white/10 data-start:rounded-s-lg data-end:rounded-e-lg data-end-preview:rounded-e-lg first-of-type:rounded-s-lg last-of-type:rounded-e-lg [&[data-selected]+[data-selected]]:rounded-s-none [[data-in-range]:not([data-selected]):not([data-end-preview])+&[data-outside]]:bg-linear-to-r [&[data-outside]:has(+[data-in-range])]:bg-linear-to-l rtl:[[data-in-range]:not([data-selected]):not([data-end-preview])+&[data-outside]]:bg-linear-to-l rtl:[&[data-outside]:has(+[data-in-range])]:bg-linear-to-r data-outside:opacity-50 from-zinc-100 dark:from-white/10 from-1% [&[data-outside]:has(+[data-in-range][data-selected])]:bg-none!">
|
||||
<ui-tooltip position="top">
|
||||
<button type="button" class="{{ $sizeClasses }} text-sm font-medium text-zinc-800 dark:text-white flex flex-col items-center justify-center rounded-lg hover:bg-zinc-800/5 dark:hover:bg-white/5 [td[data-selected]:has(+td[data-selected])_&]:rounded-e-none [td[data-selected]+td[data-selected]_&]:rounded-s-none [td[data-selected]_&]:bg-[var(--color-accent)] [td[data-selected]_&]:text-[var(--color-accent-foreground)] [td[data-selected]_&[disabled]]:opacity-50 disabled:text-zinc-400 disabled:pointer-events-none disabled:cursor-default [[readonly]_&]:pointer-events-none [[readonly]_&]:cursor-default [[readonly]_&]:bg-transparent">
|
||||
<div class="relative">
|
||||
<div class="absolute inset-x-0 bottom-[-3px] hidden [td[data-today]_&]:flex justify-center items-end"><div class="size-1 rounded-full bg-zinc-800 dark:bg-white [td[data-selected]_&]:bg-white dark:[td[data-selected]_&]:bg-zinc-800"></div></div>
|
||||
|
||||
<div><slot></slot></div>
|
||||
|
||||
<template name="subtext">
|
||||
<div class="absolute inset-x-0 bottom-[-1rem] flex justify-center font-medium text-xs text-zinc-400 dark:text-zinc-500 [[data-date-variant='success']_&]:text-lime-600 dark:[[data-date-variant='success']_&]:text-lime-400 [[data-date-variant='warning']_&]:text-yellow-600 dark:[[data-date-variant='warning']_&]:text-yellow-400 [[data-date-variant='danger']_&]:text-rose-500 dark:[[data-date-variant='danger']_&]:text-rose-400">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<template name="details">
|
||||
<div popover="manual" class="relative py-2 px-2.5 rounded-md text-xs text-white font-medium bg-zinc-800 dark:bg-zinc-700 dark:border dark:border-white/10 p-0 overflow-visible">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
</ui-tooltip>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
</ui-calendar-months>
|
||||
</ui-calendar>
|
||||
29
resources/views/flux/callout/heading.blade.php
Normal file
29
resources/views/flux/callout/heading.blade.php
Normal file
@@ -0,0 +1,29 @@
|
||||
@blaze
|
||||
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'iconVariant' => 'mini',
|
||||
'icon' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('flex items-center gap-2 text-sm font-medium')
|
||||
;
|
||||
|
||||
$iconClasses = Flux::classes()
|
||||
->add('inline-block size-5 text-[var(--callout-icon)] dark:text-[var(--callout-icon)]')
|
||||
->add($attributes->pluck('class:icon'))
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }} data-slot="heading">
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<flux:icon :icon="$icon" :variant="$iconVariant" :class="$iconClasses" />
|
||||
<?php elseif ($icon): ?>
|
||||
{{ $icon }}
|
||||
<?php endif; ?>
|
||||
|
||||
{{ $slot }}
|
||||
</div>
|
||||
222
resources/views/flux/callout/index.blade.php
Normal file
222
resources/views/flux/callout/index.blade.php
Normal file
@@ -0,0 +1,222 @@
|
||||
@blaze
|
||||
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'iconVariant' => 'mini',
|
||||
'controls' => null,
|
||||
'heading' => null,
|
||||
'color' => 'white',
|
||||
'variant' => null,
|
||||
'actions' => null,
|
||||
'content' => null,
|
||||
'inline' => null,
|
||||
'text' => null,
|
||||
'icon' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
if ($color === 'gray') $color = 'zinc';
|
||||
|
||||
$color = match($variant) {
|
||||
'success' => 'green',
|
||||
'danger' => 'red',
|
||||
'warning' => 'yellow',
|
||||
'secondary' => 'zinc',
|
||||
default => $color,
|
||||
};
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('@container p-2 flex border rounded-xl')
|
||||
->add([
|
||||
'border-(--callout-border) bg-(--callout-background)',
|
||||
'[&_[data-slot=heading]]:text-(--callout-heading)',
|
||||
'[&_[data-slot=text]]:text-(--callout-text)',
|
||||
])
|
||||
->add(match($color) {
|
||||
'blue' => [
|
||||
'[--callout-border:var(--color-blue-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-blue-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-blue-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-blue-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-blue-600)] dark:[--callout-heading:var(--color-blue-200)]',
|
||||
'[--callout-text:var(--color-blue-600)] dark:[--callout-text:var(--color-blue-300)]',
|
||||
'[--callout-icon:var(--color-blue-500)] dark:[--callout-icon:var(--color-blue-400)]',
|
||||
],
|
||||
'sky' => [
|
||||
'[--callout-border:var(--color-sky-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-sky-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-sky-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-sky-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-sky-600)] dark:[--callout-heading:var(--color-sky-200)]',
|
||||
'[--callout-text:var(--color-sky-600)] dark:[--callout-text:var(--color-sky-300)]',
|
||||
'[--callout-icon:var(--color-sky-500)] dark:[--callout-icon:var(--color-sky-400)]',
|
||||
],
|
||||
'red' => [
|
||||
'[--callout-border:var(--color-red-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-red-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-red-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-red-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-red-700)] dark:[--callout-heading:var(--color-red-200)]',
|
||||
'[--callout-text:var(--color-red-700)] dark:[--callout-text:var(--color-red-300)]',
|
||||
'[--callout-icon:var(--color-red-400)] dark:[--callout-icon:var(--color-red-400)]',
|
||||
],
|
||||
'orange' => [
|
||||
'[--callout-border:var(--color-orange-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-orange-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-orange-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-orange-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-orange-600)] dark:[--callout-heading:var(--color-orange-200)]',
|
||||
'[--callout-text:var(--color-orange-600)] dark:[--callout-text:var(--color-orange-300)]',
|
||||
'[--callout-icon:var(--color-orange-500)] dark:[--callout-icon:var(--color-orange-400)]',
|
||||
],
|
||||
'amber' => [
|
||||
'[--callout-border:var(--color-amber-400)] dark:[--callout-border:color-mix(in_oklab,var(--color-amber-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-amber-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-amber-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-amber-600)] dark:[--callout-heading:var(--color-amber-200)]',
|
||||
'[--callout-text:var(--color-amber-600)] dark:[--callout-text:var(--color-amber-300)]',
|
||||
'[--callout-icon:var(--color-amber-500)] dark:[--callout-icon:var(--color-amber-400)]',
|
||||
],
|
||||
'yellow' => [
|
||||
'[--callout-border:var(--color-yellow-400)] dark:[--callout-border:color-mix(in_oklab,var(--color-yellow-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-yellow-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-yellow-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-yellow-600)] dark:[--callout-heading:var(--color-yellow-200)]',
|
||||
'[--callout-text:var(--color-yellow-700)] dark:[--callout-text:var(--color-yellow-300)]',
|
||||
'[--callout-icon:var(--color-yellow-500)] dark:[--callout-icon:var(--color-yellow-400)]',
|
||||
],
|
||||
'lime' => [
|
||||
'[--callout-border:var(--color-lime-400)] dark:[--callout-border:color-mix(in_oklab,var(--color-lime-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-lime-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-lime-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-lime-700)] dark:[--callout-heading:var(--color-lime-200)]',
|
||||
'[--callout-text:var(--color-lime-600)] dark:[--callout-text:var(--color-lime-300)]',
|
||||
'[--callout-icon:var(--color-lime-500)] dark:[--callout-icon:var(--color-lime-400)]',
|
||||
],
|
||||
'green' => [
|
||||
'[--callout-border:var(--color-green-300)] dark:[--callout-border:color-mix(in_oklab,var(--color-green-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-green-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-green-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-green-600)] dark:[--callout-heading:var(--color-green-200)]',
|
||||
'[--callout-text:var(--color-green-600)] dark:[--callout-text:var(--color-green-300)]',
|
||||
'[--callout-icon:var(--color-green-500)] dark:[--callout-icon:var(--color-green-400)]',
|
||||
],
|
||||
'emerald' => [
|
||||
'[--callout-border:var(--color-emerald-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-emerald-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-emerald-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-emerald-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-emerald-600)] dark:[--callout-heading:var(--color-emerald-200)]',
|
||||
'[--callout-text:var(--color-emerald-600)] dark:[--callout-text:var(--color-emerald-300)]',
|
||||
'[--callout-icon:var(--color-emerald-500)] dark:[--callout-icon:var(--color-emerald-400)]',
|
||||
],
|
||||
'teal' => [
|
||||
'[--callout-border:var(--color-teal-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-teal-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-teal-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-teal-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-teal-600)] dark:[--callout-heading:var(--color-teal-200)]',
|
||||
'[--callout-text:var(--color-teal-600)] dark:[--callout-text:var(--color-teal-300)]',
|
||||
'[--callout-icon:var(--color-teal-500)] dark:[--callout-icon:var(--color-teal-400)]',
|
||||
],
|
||||
'cyan' => [
|
||||
'[--callout-border:var(--color-cyan-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-cyan-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-cyan-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-cyan-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-cyan-600)] dark:[--callout-heading:var(--color-cyan-200)]',
|
||||
'[--callout-text:var(--color-cyan-600)] dark:[--callout-text:var(--color-cyan-300)]',
|
||||
'[--callout-icon:var(--color-cyan-500)] dark:[--callout-icon:var(--color-cyan-400)]',
|
||||
],
|
||||
'indigo' => [
|
||||
'[--callout-border:var(--color-indigo-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-indigo-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-indigo-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-indigo-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-indigo-600)] dark:[--callout-heading:var(--color-indigo-200)]',
|
||||
'[--callout-text:var(--color-indigo-600)] dark:[--callout-text:var(--color-indigo-300)]',
|
||||
'[--callout-icon:var(--color-indigo-500)] dark:[--callout-icon:var(--color-indigo-400)]',
|
||||
],
|
||||
'violet' => [
|
||||
'[--callout-border:var(--color-violet-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-violet-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-violet-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-violet-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-violet-600)] dark:[--callout-heading:var(--color-violet-200)]',
|
||||
'[--callout-text:var(--color-violet-600)] dark:[--callout-text:var(--color-violet-300)]',
|
||||
'[--callout-icon:var(--color-violet-500)] dark:[--callout-icon:var(--color-violet-400)]',
|
||||
],
|
||||
'purple' => [
|
||||
'[--callout-border:var(--color-purple-300)] dark:[--callout-border:color-mix(in_oklab,var(--color-purple-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-purple-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-purple-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-purple-800)] dark:[--callout-heading:var(--color-purple-200)]',
|
||||
'[--callout-text:var(--color-purple-700)] dark:[--callout-text:var(--color-purple-300)]',
|
||||
'[--callout-icon:var(--color-purple-500)] dark:[--callout-icon:var(--color-purple-400)]',
|
||||
],
|
||||
'fuchsia' => [
|
||||
'[--callout-border:var(--color-fuchsia-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-fuchsia-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-fuchsia-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-fuchsia-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-fuchsia-600)] dark:[--callout-heading:var(--color-fuchsia-200)]',
|
||||
'[--callout-text:var(--color-fuchsia-600)] dark:[--callout-text:var(--color-fuchsia-300)]',
|
||||
'[--callout-icon:var(--color-fuchsia-500)] dark:[--callout-icon:var(--color-fuchsia-400)]',
|
||||
],
|
||||
'pink' => [
|
||||
'[--callout-border:var(--color-pink-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-pink-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-pink-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-pink-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-pink-600)] dark:[--callout-heading:var(--color-pink-200)]',
|
||||
'[--callout-text:var(--color-pink-600)] dark:[--callout-text:var(--color-pink-300)]',
|
||||
'[--callout-icon:var(--color-pink-500)] dark:[--callout-icon:var(--color-pink-400)]',
|
||||
],
|
||||
'rose' => [
|
||||
'[--callout-border:var(--color-rose-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-rose-400),transparent_50%)]',
|
||||
'[--callout-background:var(--color-rose-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-rose-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-rose-600)] dark:[--callout-heading:var(--color-rose-200)]',
|
||||
'[--callout-text:var(--color-rose-600)] dark:[--callout-text:var(--color-rose-300)]',
|
||||
'[--callout-icon:var(--color-rose-500)] dark:[--callout-icon:var(--color-rose-400)]',
|
||||
],
|
||||
'zinc' => [
|
||||
'[--callout-border:var(--color-zinc-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-white),transparent_95%)]',
|
||||
'[--callout-background:var(--color-zinc-50)] dark:[--callout-background:color-mix(in_oklab,var(--color-zinc-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-zinc-800)] dark:[--callout-heading:var(--color-zinc-200)]',
|
||||
'[--callout-text:var(--color-zinc-500)] dark:[--callout-text:var(--color-zinc-300)]',
|
||||
'[--callout-icon:var(--color-zinc-400)] dark:[--callout-icon:var(--color-zinc-400)]',
|
||||
],
|
||||
default => [
|
||||
'[--callout-border:var(--color-zinc-200)] dark:[--callout-border:color-mix(in_oklab,var(--color-white),transparent_95%)]',
|
||||
'[--callout-background:var(--color-white)] dark:[--callout-background:color-mix(in_oklab,var(--color-zinc-400),transparent_90%)]',
|
||||
'[--callout-heading:var(--color-zinc-800)] dark:[--callout-heading:var(--color-zinc-200)]',
|
||||
'[--callout-text:var(--color-zinc-500)] dark:[--callout-text:var(--color-zinc-300)]',
|
||||
'[--callout-icon:var(--color-zinc-400)] dark:[--callout-icon:var(--color-zinc-400)]',
|
||||
],
|
||||
})
|
||||
;
|
||||
|
||||
$iconWrapperClasses = Flux::classes()
|
||||
->add('ps-2 py-2 pe-0 flex items-baseline')
|
||||
;
|
||||
|
||||
$iconClasses = Flux::classes()
|
||||
->add('inline-block size-5 text-[var(--callout-icon)] dark:text-[var(--callout-icon)]')
|
||||
->add($attributes->pluck('class:icon'))
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }} data-flux-callout>
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<div class="{{ $iconWrapperClasses }}">
|
||||
<flux:icon :icon="$icon" :variant="$iconVariant" :class="$iconClasses" />
|
||||
</div>
|
||||
<?php elseif ($icon): ?>
|
||||
<div {{ $icon->attributes->class($iconWrapperClasses) }}>
|
||||
{{ $icon }}
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="ps-2 flex-1 {{ $inline ? '@md:flex @md:[&>[data-slot="content"]:has([data-slot="heading"]):has([data-slot="text"])+[data-slot="actions"]]:p-2' : '' }}">
|
||||
<div class="flex-1 py-2 pe-3 @md:pe-4 flex flex-col justify-center gap-2" data-slot="content">
|
||||
<?php if ($heading): ?>
|
||||
<flux:callout.heading>{{ $heading }}</flux:callout.heading>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($text): ?>
|
||||
<flux:callout.text>{{ $text }}</flux:callout.text>
|
||||
<?php endif; ?>
|
||||
|
||||
{{ $content ?? $slot }}
|
||||
</div>
|
||||
|
||||
<?php if ($actions): ?>
|
||||
<div {{ $actions->attributes->class([
|
||||
$inline ? '@max-md:py-2 @md:m-[-2px] @md:ps-4 @md:justify-end @md:flex-row-reverse' : 'py-2',
|
||||
'self-start flex items-center gap-2'
|
||||
]) }} data-slot="actions">
|
||||
{{ $actions }}
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($controls): ?>
|
||||
<div {{ $controls->attributes->class($inline ? 'ps-2 m-[-2px]' : 'ps-2') }}>
|
||||
{{ $controls }}
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
15
resources/views/flux/callout/link.blade.php
Normal file
15
resources/views/flux/callout/link.blade.php
Normal file
@@ -0,0 +1,15 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'external' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('inline font-medium')
|
||||
->add('underline underline-offset-[6px] hover:decoration-current')
|
||||
->add('decoration-zinc-800/20 dark:decoration-white/20')
|
||||
;
|
||||
@endphp
|
||||
{{-- NOTE: It's important that this file has NO newline at the end of the file. --}}
|
||||
<a {{ $attributes->class($classes) }} <?php if ($external) : ?>target="_blank"<?php endif; ?>>{{ $slot }}</a>
|
||||
5
resources/views/flux/callout/text.blade.php
Normal file
5
resources/views/flux/callout/text.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@blaze
|
||||
|
||||
<div {{ $attributes->class('text-sm') }} data-slot="text">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
20
resources/views/flux/card/index.blade.php
Normal file
20
resources/views/flux/card/index.blade.php
Normal file
@@ -0,0 +1,20 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'size' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('[:where(&)]:bg-bg-surface')
|
||||
->add('border border-border-subtle')
|
||||
->add(match ($size) {
|
||||
default => '[:where(&)]:p-6 [:where(&)]:rounded-xl',
|
||||
'sm' => '[:where(&)]:p-4 [:where(&)]:rounded-lg',
|
||||
})
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }} data-flux-card>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
9
resources/views/flux/chart/area.blade.php
Normal file
9
resources/views/flux/chart/area.blade.php
Normal file
@@ -0,0 +1,9 @@
|
||||
@aware(['field'])
|
||||
|
||||
@props([
|
||||
'field' => 'value',
|
||||
])
|
||||
|
||||
<template name="area" field="{{ $field }}" {{ $attributes->only(['curve']) }}>
|
||||
<path {{ $attributes->except('curve')->merge(['fill' => 'currentColor']) }}></path>
|
||||
</template>
|
||||
21
resources/views/flux/chart/axis/grid.blade.php
Normal file
21
resources/views/flux/chart/axis/grid.blade.php
Normal file
@@ -0,0 +1,21 @@
|
||||
@aware(['axis' => 'x'])
|
||||
|
||||
@if ($axis === 'x')
|
||||
<template name="grid-line">
|
||||
<line {{ $attributes->merge([
|
||||
'type' => 'horizontal',
|
||||
'class' => 'text-zinc-200/50 dark:text-white/15',
|
||||
'stroke' => 'currentColor',
|
||||
'stroke-width' => '1',
|
||||
]) }}></line>
|
||||
</template>
|
||||
@else
|
||||
<template name="grid-line">
|
||||
<line {{ $attributes->merge([
|
||||
'type' => 'vertical',
|
||||
'class' => 'text-zinc-200/50 dark:text-white/15',
|
||||
'stroke' => 'currentColor',
|
||||
'stroke-width' => '1',
|
||||
]) }}></line>
|
||||
</template>
|
||||
@endif
|
||||
25
resources/views/flux/chart/axis/index.blade.php
Normal file
25
resources/views/flux/chart/axis/index.blade.php
Normal file
@@ -0,0 +1,25 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'axis' => 'x',
|
||||
'format' => null,
|
||||
'field' => 'index',
|
||||
'position' => null,
|
||||
'tickValues' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$format = is_array($format) ? \Illuminate\Support\Js::encode($format) : $format;
|
||||
|
||||
$field ??= $axis === 'x' ? 'date' : $field;
|
||||
@endphp
|
||||
|
||||
<template {{ $attributes->merge([
|
||||
'name' => 'axis',
|
||||
'axis' => $axis,
|
||||
'format' => $format,
|
||||
'position' => $position,
|
||||
'tick-values' => is_string($tickValues) ? $tickValues : json_encode($tickValues),
|
||||
]) }} @if ($field) field="{{ $field }}" @endif>
|
||||
{{ $slot }}
|
||||
</template>
|
||||
23
resources/views/flux/chart/axis/line.blade.php
Normal file
23
resources/views/flux/chart/axis/line.blade.php
Normal file
@@ -0,0 +1,23 @@
|
||||
@aware(['axis' => 'x'])
|
||||
|
||||
@if ($axis === 'x')
|
||||
<template name="axis-line">
|
||||
<line {{ $attributes->merge([
|
||||
'class' => '[:where(&)]:text-zinc-300 dark:[:where(&)]:text-white/40',
|
||||
'orientation' => 'bottom',
|
||||
'stroke-width' => '1',
|
||||
'stroke' => 'currentColor',
|
||||
'fill' => 'none',
|
||||
]) }}></line>
|
||||
</template>
|
||||
@else
|
||||
<template name="axis-line">
|
||||
<line {{ $attributes->merge([
|
||||
'class' => '[:where(&)]:text-zinc-300 dark:[:where(&)]:text-white/40',
|
||||
'orientation' => 'left',
|
||||
'stroke-width' => '1',
|
||||
'stroke' => 'currentColor',
|
||||
'fill' => 'none',
|
||||
]) }}></line>
|
||||
</template>
|
||||
@endif
|
||||
31
resources/views/flux/chart/axis/mark.blade.php
Normal file
31
resources/views/flux/chart/axis/mark.blade.php
Normal file
@@ -0,0 +1,31 @@
|
||||
@aware(['axis' => 'x', 'position' => null])
|
||||
|
||||
@if ($axis === 'x')
|
||||
<template name="tick-mark">
|
||||
<g>
|
||||
<line {{ $attributes->merge([
|
||||
'class' => 'stroke-zinc-300',
|
||||
'orientation' => $position === 'top' ? 'top' : 'bottom',
|
||||
'stroke' => 'currentColor',
|
||||
'stroke-width' => '1',
|
||||
'fill' => 'none',
|
||||
'y1' => '0',
|
||||
'y2' => '6',
|
||||
]) }}></line>
|
||||
</g>
|
||||
</template>
|
||||
@else
|
||||
<template name="tick-mark">
|
||||
<g>
|
||||
<line {{ $attributes->merge([
|
||||
'class' => 'stroke-zinc-300',
|
||||
'orientation' => $position === 'right' ? 'right' : 'left',
|
||||
'stroke' => 'currentColor',
|
||||
'stroke-width' => '1',
|
||||
'fill' => 'none',
|
||||
'x1' => $position === 'right' ? '0' : '-6',
|
||||
'x2' => $position === 'right' ? '6' : '0',
|
||||
]) }}></line>
|
||||
</g>
|
||||
</template>
|
||||
@endif
|
||||
35
resources/views/flux/chart/axis/tick.blade.php
Normal file
35
resources/views/flux/chart/axis/tick.blade.php
Normal file
@@ -0,0 +1,35 @@
|
||||
@aware(['axis' => 'x', 'position' => null ])
|
||||
|
||||
@props([
|
||||
'format' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$format = is_array($format) ? \Illuminate\Support\Js::encode($format) : $format;
|
||||
@endphp
|
||||
|
||||
@if ($axis === 'x')
|
||||
<template name="tick-label" @if ($format) format="{{ $format }}" @endif>
|
||||
<g>
|
||||
<text {{ $attributes->merge([
|
||||
'class' => '[:where(&)]:text-xs [:where(&)]:text-zinc-400 [:where(&)]:font-medium [:where(&)]:dark:text-zinc-300',
|
||||
'text-anchor' => 'middle',
|
||||
'fill' => 'currentColor',
|
||||
'dominant-baseline' => $position === 'top' ? 'text-after-edge' : 'text-before-edge',
|
||||
'dy' => $position === 'top' ? '-1em' : '1em',
|
||||
]) }}><slot></slot></text>
|
||||
</g>
|
||||
</template>
|
||||
@else
|
||||
<template name="tick-label" @if ($format) format="{{ $format }}" @endif>
|
||||
<g>
|
||||
<text {{ $attributes->merge([
|
||||
'class' => '[:where(&)]:text-xs [:where(&)]:text-zinc-400 [:where(&)]:dark:text-zinc-300',
|
||||
'dominant-baseline' => 'central',
|
||||
'fill' => 'currentColor',
|
||||
'text-anchor' => $position === 'right' ? 'start' : 'end',
|
||||
'dx' => $position === 'right' ? '1em' : '-1em',
|
||||
]) }}><slot></slot></text>
|
||||
</g>
|
||||
</template>
|
||||
@endif
|
||||
11
resources/views/flux/chart/cursor.blade.php
Normal file
11
resources/views/flux/chart/cursor.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
<template name="cursor">
|
||||
<line {{ $attributes->merge([
|
||||
'class' => 'text-zinc-500 dark:text-zinc-300',
|
||||
'type' => 'vertical',
|
||||
'stroke' => 'currentColor',
|
||||
'stroke-width' => '1',
|
||||
'stroke-dasharray' => '4,4',
|
||||
]) }}></line>
|
||||
</template>
|
||||
18
resources/views/flux/chart/index.blade.php
Normal file
18
resources/views/flux/chart/index.blade.php
Normal file
@@ -0,0 +1,18 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'tooltip' => null,
|
||||
'summary' => null,
|
||||
'value' => null,
|
||||
'svg' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes('block [:where(&)]:relative');
|
||||
|
||||
$value = is_array($value) ? \Illuminate\Support\Js::encode($value) : $value;
|
||||
@endphp
|
||||
|
||||
<ui-chart {{ $attributes->class($classes) }} wire:ignore.children @if ($value) value="{{ $value }}" @endif>
|
||||
{{ $slot }}
|
||||
</ui-chart>
|
||||
21
resources/views/flux/chart/legend/index.blade.php
Normal file
21
resources/views/flux/chart/legend/index.blade.php
Normal file
@@ -0,0 +1,21 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'label' => null,
|
||||
'field' => null,
|
||||
'format' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$format = is_array($format) ? \Illuminate\Support\Js::encode($format) : $format;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class(['flex items-center gap-2 p-2']) }}>
|
||||
{{ $slot }}
|
||||
|
||||
@if (is_string($label) && $label !== '')
|
||||
<div class="text-xs text-zinc-500 dark:text-zinc-400">{{ $label }}</div>
|
||||
@elseif ($label)
|
||||
{{ $label }}
|
||||
@endif
|
||||
</div>
|
||||
3
resources/views/flux/chart/legend/indicator.blade.php
Normal file
3
resources/views/flux/chart/legend/indicator.blade.php
Normal file
@@ -0,0 +1,3 @@
|
||||
@blaze
|
||||
|
||||
<div {{ $attributes->class('size-2.5 rounded-full') }}></div>
|
||||
15
resources/views/flux/chart/line.blade.php
Normal file
15
resources/views/flux/chart/line.blade.php
Normal file
@@ -0,0 +1,15 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'field' => 'value',
|
||||
])
|
||||
|
||||
<template name="line" field="{{ $field }}" {{ $attributes->only(['curve']) }}>
|
||||
<path {{ $attributes->class('[:where(&)]:text-zinc-800')->merge([
|
||||
'stroke' => 'currentColor',
|
||||
'stroke-width' => '2',
|
||||
'fill' => 'none',
|
||||
'stroke-linecap' => 'round',
|
||||
'stroke-linejoin' => 'round',
|
||||
]) }}></path>
|
||||
</template>
|
||||
13
resources/views/flux/chart/point.blade.php
Normal file
13
resources/views/flux/chart/point.blade.php
Normal file
@@ -0,0 +1,13 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'field' => 'value',
|
||||
])
|
||||
|
||||
<template name="point" field="{{ $field }}">
|
||||
<circle {{ $attributes->class('[:where(&)]:text-zinc-800 dark:[:where(&)]:text-zinc-100 [:where(&)]:stroke-white dark:[:where(&)]:stroke-zinc-900')->merge([
|
||||
'r' => '4',
|
||||
'fill' => 'currentColor',
|
||||
'stroke-width' => '1',
|
||||
]) }}></circle>
|
||||
</template>
|
||||
7
resources/views/flux/chart/summary/index.blade.php
Normal file
7
resources/views/flux/chart/summary/index.blade.php
Normal file
@@ -0,0 +1,7 @@
|
||||
@blaze
|
||||
|
||||
<template name="summary">
|
||||
<div {{ $attributes }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</template>
|
||||
15
resources/views/flux/chart/summary/value.blade.php
Normal file
15
resources/views/flux/chart/summary/value.blade.php
Normal file
@@ -0,0 +1,15 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'field' => null,
|
||||
'format' => null,
|
||||
'fallback' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$format = is_array($format) ? \Illuminate\Support\Js::encode($format) : $format;
|
||||
@endphp
|
||||
|
||||
<span {{ $attributes }}>
|
||||
<slot @if ($field) field="{{ $field }}" @endif @if ($format) format="{{ $format }}" @endif @if ($fallback) fallback="{{ $fallback }}" @endif></slot>
|
||||
</span>
|
||||
11
resources/views/flux/chart/svg.blade.php
Normal file
11
resources/views/flux/chart/svg.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'gutter' => null,
|
||||
])
|
||||
|
||||
<template name="svg" @if (isset($gutter)) gutter="{{ $gutter }}" @endif>
|
||||
<svg {{ $attributes->class('absolute inset-0') }} xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||||
{{ $slot }}
|
||||
</svg>
|
||||
</template>
|
||||
17
resources/views/flux/chart/tooltip/heading.blade.php
Normal file
17
resources/views/flux/chart/tooltip/heading.blade.php
Normal file
@@ -0,0 +1,17 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'field' => 'date',
|
||||
'format' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$format = is_array($format) ? \Illuminate\Support\Js::encode($format) : $format;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class([
|
||||
'bg-zinc-50 border-b border-zinc-200 dark:bg-zinc-600 dark:border-zinc-500 flex justify-between items-center p-2',
|
||||
'text-xs font-medium [:where(&)]:text-zinc-800 dark:[:where(&)]:text-zinc-100'
|
||||
]) }}>
|
||||
<slot field="{{ $field }}" @if ($format) format="{{ $format }}" @endif></slot>
|
||||
</div>
|
||||
19
resources/views/flux/chart/tooltip/index.blade.php
Normal file
19
resources/views/flux/chart/tooltip/index.blade.php
Normal file
@@ -0,0 +1,19 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'field' => null,
|
||||
'format' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$format = is_array($format) ? \Illuminate\Support\Js::encode($format) : $format;
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('opacity-0 data-active:opacity-100 absolute flex flex-col rounded-lg overflow-hidden shadow-lg border border-zinc-200 bg-white dark:border-zinc-500 dark:bg-zinc-700');
|
||||
@endphp
|
||||
|
||||
<template name="tooltip">
|
||||
<div {{ $attributes->class($classes) }}>
|
||||
{{ $slot}}
|
||||
</div>
|
||||
</template>
|
||||
27
resources/views/flux/chart/tooltip/value.blade.php
Normal file
27
resources/views/flux/chart/tooltip/value.blade.php
Normal file
@@ -0,0 +1,27 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'label' => null,
|
||||
'field' => null,
|
||||
'format' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$format = is_array($format) ? \Illuminate\Support\Js::encode($format) : $format;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class(['flex items-center gap-2 p-2 text-xs [:where(&)]:text-zinc-500 dark:[:where(&)]:text-zinc-300']) }}>
|
||||
{{ $slot }}
|
||||
|
||||
@if (is_string($label) && $label !== '')
|
||||
<div class="text-zinc-800 dark:text-white">{{ $label }}</div>
|
||||
@elseif ($label)
|
||||
{{ $label }}
|
||||
@endif
|
||||
|
||||
@if ($field)
|
||||
<div class="flex-1"></div>
|
||||
|
||||
<slot field="{{ $field }}" @if ($format) format="{{ $format }}" @endif></slot>
|
||||
@endif
|
||||
</div>
|
||||
14
resources/views/flux/chart/value.blade.php
Normal file
14
resources/views/flux/chart/value.blade.php
Normal file
@@ -0,0 +1,14 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'field' => null,
|
||||
'format' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$format = is_array($format) ? \Illuminate\Support\Js::encode($format) : $format;
|
||||
@endphp
|
||||
|
||||
<span {{ $attributes }}>
|
||||
<slot @if ($field) field="{{ $field }}" @endif @if ($format) format="{{ $format }}" @endif></slot>
|
||||
</span>
|
||||
5
resources/views/flux/chart/viewport.blade.php
Normal file
5
resources/views/flux/chart/viewport.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@blaze
|
||||
|
||||
<div {{ $attributes->class('[:where(&)]:relative') }}>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
15
resources/views/flux/chart/zero-line.blade.php
Normal file
15
resources/views/flux/chart/zero-line.blade.php
Normal file
@@ -0,0 +1,15 @@
|
||||
@aware(['axis' => 'x'])
|
||||
|
||||
<template name="zero-line">
|
||||
<line {{ $attributes->merge([
|
||||
'class' => '[:where(&)]:text-zinc-400',
|
||||
'orientation' => 'left',
|
||||
'stroke-width' => '1',
|
||||
'stroke' => 'currentColor',
|
||||
'fill' => 'none',
|
||||
'x1' => '0',
|
||||
'y1' => '0',
|
||||
'x2' => '0',
|
||||
'y2' => '6',
|
||||
]) }}></line>
|
||||
</template>
|
||||
2
resources/views/flux/checkbox/all.blade.php
Normal file
2
resources/views/flux/checkbox/all.blade.php
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
<flux:checkbox all :$attributes />
|
||||
5
resources/views/flux/checkbox/group/index.blade.php
Normal file
5
resources/views/flux/checkbox/group/index.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@props([
|
||||
'variant' => 'default',
|
||||
])
|
||||
|
||||
<flux:delegate-component :component="'checkbox.group.variants.' . $variant">{{ $slot }}</flux:delegate-component>
|
||||
@@ -0,0 +1,25 @@
|
||||
@props([
|
||||
'variant' => null,
|
||||
'size' => null,
|
||||
'name' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
// We only want to show the name attribute on the checkbox if it has been set
|
||||
// manually, but not if it has been set from the wire:model attribute...
|
||||
$showName = isset($name);
|
||||
|
||||
if (! isset($name)) {
|
||||
$name = $attributes->whereStartsWith('wire:model')->first();
|
||||
}
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('flex flex-wrap gap-2')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<flux:with-field :$attributes>
|
||||
<ui-checkbox-group {{ $attributes->class($classes) }} @if($showName) name="{{ $name }}" @endif data-flux-checkbox-group-buttons>
|
||||
{{ $slot }}
|
||||
</ui-checkbox-group>
|
||||
</flux:with-field>
|
||||
25
resources/views/flux/checkbox/group/variants/cards.blade.php
Normal file
25
resources/views/flux/checkbox/group/variants/cards.blade.php
Normal file
@@ -0,0 +1,25 @@
|
||||
@props([
|
||||
'variant' => null,
|
||||
'size' => null,
|
||||
'name' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
// We only want to show the name attribute on the checkbox if it has been set
|
||||
// manually, but not if it has been set from the wire:model attribute...
|
||||
$showName = isset($name);
|
||||
|
||||
if (! isset($name)) {
|
||||
$name = $attributes->whereStartsWith('wire:model')->first();
|
||||
}
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('flex gap-3')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<flux:with-field :$attributes>
|
||||
<ui-checkbox-group {{ $attributes->class($classes) }} @if($showName) name="{{ $name }}" @endif data-flux-checkbox-group-cards>
|
||||
{{ $slot }}
|
||||
</ui-checkbox-group>
|
||||
</flux:with-field>
|
||||
@@ -0,0 +1,22 @@
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('*:data-flux-field:mb-3')
|
||||
->add('[&>[data-flux-field]:has(>[data-flux-description])]:mb-4')
|
||||
->add('[&>[data-flux-field]:last-child]:mb-0!')
|
||||
;
|
||||
|
||||
// Support adding the .self modifier to the wire:model directive...
|
||||
if (($wireModel = $attributes->wire('model')) && $wireModel->directive && ! $wireModel->hasModifier('self')) {
|
||||
unset($attributes[$wireModel->directive]);
|
||||
|
||||
$wireModel->directive .= '.self';
|
||||
|
||||
$attributes = $attributes->merge([$wireModel->directive => $wireModel->value]);
|
||||
}
|
||||
@endphp
|
||||
|
||||
<flux:with-field :$attributes>
|
||||
<ui-checkbox-group {{ $attributes->class($classes) }} data-flux-checkbox-group>
|
||||
{{ $slot }}
|
||||
</ui-checkbox-group>
|
||||
</flux:with-field>
|
||||
25
resources/views/flux/checkbox/group/variants/pills.blade.php
Normal file
25
resources/views/flux/checkbox/group/variants/pills.blade.php
Normal file
@@ -0,0 +1,25 @@
|
||||
@props([
|
||||
'variant' => null,
|
||||
'size' => null,
|
||||
'name' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
// We only want to show the name attribute on the checkbox if it has been set
|
||||
// manually, but not if it has been set from the wire:model attribute...
|
||||
$showName = isset($name);
|
||||
|
||||
if (! isset($name)) {
|
||||
$name = $attributes->whereStartsWith('wire:model')->first();
|
||||
}
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('flex flex-wrap gap-3')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<flux:with-field :$attributes>
|
||||
<ui-checkbox-group {{ $attributes->class($classes) }} @if($showName) name="{{ $name }}" @endif data-flux-checkbox-group-pills>
|
||||
{{ $slot }}
|
||||
</ui-checkbox-group>
|
||||
</flux:with-field>
|
||||
16
resources/views/flux/checkbox/index.blade.php
Normal file
16
resources/views/flux/checkbox/index.blade.php
Normal file
@@ -0,0 +1,16 @@
|
||||
@blaze
|
||||
|
||||
@aware([ 'variant' ])
|
||||
|
||||
@props([
|
||||
'variant' => 'default',
|
||||
])
|
||||
|
||||
@php
|
||||
// This prevents variants picked up by `@aware()` from other wrapping components like flux::modal from being used here...
|
||||
$variant = $variant !== 'default' && Flux::componentExists('checkbox.variants.' . $variant)
|
||||
? $variant
|
||||
: 'default';
|
||||
@endphp
|
||||
|
||||
<flux:delegate-component :component="'checkbox.variants.' . $variant">{{ $slot }}</flux:delegate-component>
|
||||
32
resources/views/flux/checkbox/indicator.blade.php
Normal file
32
resources/views/flux/checkbox/indicator.blade.php
Normal file
@@ -0,0 +1,32 @@
|
||||
@blaze
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('shrink-0 size-[1.125rem] rounded-[.3rem] flex justify-center items-center')
|
||||
->add('text-sm text-zinc-700 dark:text-zinc-800')
|
||||
->add('shadow-xs [ui-checkbox[disabled]_&]:opacity-75 [ui-checkbox[data-checked][disabled]_&]:opacity-50 [ui-checkbox[disabled]_&]:shadow-none [ui-checkbox[data-checked]_&]:shadow-none [ui-checkbox[data-indeterminate]_&]:shadow-none')
|
||||
->add('[ui-checkbox[data-checked]:not([data-indeterminate])_&>svg:first-child]:block [ui-checkbox[data-indeterminate]_&>svg:last-child]:block')
|
||||
->add([
|
||||
'border',
|
||||
'border-zinc-300 dark:border-white/10',
|
||||
'[ui-checkbox[disabled]_&]:border-zinc-200 dark:[ui-checkbox[disabled]_&]:border-white/5',
|
||||
'[ui-checkbox[data-checked]_&]:border-transparent [ui-checkbox[data-indeterminate]_&]:border-transparent',
|
||||
'[ui-checkbox[disabled][data-checked]_&]:border-transparent [ui-checkbox[disabled][data-indeterminate]_&]:border-transparent',
|
||||
'[print-color-adjust:exact]',
|
||||
])
|
||||
->add([
|
||||
'bg-white dark:bg-white/10',
|
||||
'[ui-checkbox[data-checked]_&]:bg-[var(--color-accent)]',
|
||||
'hover:[ui-checkbox[data-checked]_&]:bg-(--color-accent)',
|
||||
'focus:[ui-checkbox[data-checked]_&]:bg-(--color-accent)',
|
||||
'[ui-checkbox[data-indeterminate]_&]:bg-[var(--color-accent)]',
|
||||
'hover:[ui-checkbox[data-indeterminate]_&]:bg-(--color-accent)',
|
||||
'focus:[ui-checkbox[data-indeterminate]_&]:bg-(--color-accent)',
|
||||
])
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }} data-flux-checkbox-indicator>
|
||||
<flux:icon.check variant="micro" class="hidden text-[var(--color-accent-foreground)]" />
|
||||
<flux:icon.minus variant="micro" class="hidden text-[var(--color-accent-foreground)]" />
|
||||
</div>
|
||||
67
resources/views/flux/checkbox/variants/buttons.blade.php
Normal file
67
resources/views/flux/checkbox/variants/buttons.blade.php
Normal file
@@ -0,0 +1,67 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'accent' => true,
|
||||
'size' => 'base',
|
||||
'label' => null,
|
||||
'icon' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('flex relative items-center font-medium justify-center gap-2 whitespace-nowrap')
|
||||
->add(match ($size) {
|
||||
'base' => 'h-10 text-sm rounded-lg px-4 [&:has(>:not(span):first-child)]:ps-3 [&:has(>:not(span):last-child)]:pe-3',
|
||||
'sm' => 'h-8 text-sm rounded-md px-3',
|
||||
'xs' => 'h-6 text-xs rounded-md px-2',
|
||||
})
|
||||
->add(match ($size) {
|
||||
'base' => 'shadow-xs',
|
||||
'sm' => 'shadow-xs',
|
||||
'xs' => 'shadow-none',
|
||||
})
|
||||
->add('text-zinc-800 dark:text-white')
|
||||
->add('bg-white dark:bg-zinc-700')
|
||||
->add('after:absolute after:-inset-px after:rounded-lg')
|
||||
->add('border border-zinc-200 border-b-zinc-300/80 dark:border-zinc-600')
|
||||
->add([
|
||||
'[--haze:color-mix(in_oklab,_var(--color-accent-content),_transparent_97.5%)]',
|
||||
'[--haze-border:color-mix(in_oklab,_var(--color-accent-content),_transparent_80%)]',
|
||||
'[--haze-light:color-mix(in_oklab,_var(--color-accent),_transparent_98%)]',
|
||||
'dark:[--haze:color-mix(in_oklab,_var(--color-accent-content),_transparent_90%)]',
|
||||
])
|
||||
->add(match ($accent) {
|
||||
true => [
|
||||
'hover:border-[var(--haze-border)] dark:hover:border-zinc-500',
|
||||
'dark:data-checked:bg-white/15 data-checked:border-(--color-accent) hover:data-checked:border-(--color-accent)',
|
||||
'hover:after:bg-[var(--haze-light)] dark:hover:after:bg-white/[4%] data-checked:after:bg-(--haze) hover:data-checked:after:bg-(--haze)',
|
||||
],
|
||||
false => [
|
||||
'hover:border-zinc-200 dark:hover:border-zinc-500',
|
||||
'data-checked:bg-zinc-50 dark:data-checked:bg-white/15 data-checked:border-zinc-800 dark:data-checked:border-white',
|
||||
'hover:bg-zinc-50 dark:hover:bg-zinc-600/75',
|
||||
],
|
||||
})
|
||||
->add('disabled:opacity-75 dark:disabled:opacity-75 disabled:cursor-default disabled:pointer-events-none')
|
||||
;
|
||||
|
||||
$iconAttributes = Flux::attributesAfter('icon:', $attributes, [
|
||||
'class' => 'text-zinc-300 dark:text-zinc-400 in-data-checked:text-zinc-800 dark:in-data-checked:text-white',
|
||||
'variant' => 'micro',
|
||||
]);
|
||||
@endphp
|
||||
|
||||
{{-- We have to put tabindex="-1" here because otherwise, Livewire requests will wipe out tabindex state, --}}
|
||||
{{-- even with durable attributes for some reason... --}}
|
||||
{{-- We have to put "data-flux-field" so that a single box can be disabled without "disabling" the group field label... --}}
|
||||
<ui-checkbox {{ $attributes->class($classes) }} data-flux-control data-flux-checkbox-buttons tabindex="-1" data-flux-field>
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<flux:icon :icon="$icon" :attributes="$iconAttributes" />
|
||||
<?php elseif ($icon): ?>
|
||||
{{ $icon }}
|
||||
<?php endif; ?>
|
||||
|
||||
@if (isset($label) || $slot->isNotEmpty())
|
||||
<span>{{ $label ?? $slot }}</span>
|
||||
@endif
|
||||
</ui-checkbox>
|
||||
78
resources/views/flux/checkbox/variants/cards.blade.php
Normal file
78
resources/views/flux/checkbox/variants/cards.blade.php
Normal file
@@ -0,0 +1,78 @@
|
||||
@blaze
|
||||
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@aware([ 'indicator' ])
|
||||
|
||||
@props([
|
||||
'iconVariant' => 'micro',
|
||||
'description' => null,
|
||||
'indicator' => true,
|
||||
'accent' => true,
|
||||
'label' => null,
|
||||
'icon' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
|
||||
$iconClasses = Flux::classes()
|
||||
->add('inline-block mt-0.5 text-zinc-400 [ui-checkbox[data-checked]_&]:text-zinc-800 dark:[ui-checkbox[data-checked]_&]:text-white')
|
||||
// When using the outline icon variant, we need to size it down to match the default icon sizes...
|
||||
->add($iconVariant === 'outline' ? 'size-4' : '')
|
||||
;
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('relative flex justify-between gap-3 flex-1 p-4')
|
||||
->add('rounded-lg shadow-xs')
|
||||
->add('bg-white dark:bg-white/10 dark:hover:bg-white/15 dark:data-checked:bg-white/15')
|
||||
->add('after:absolute after:-inset-px after:rounded-lg')
|
||||
->add('border border-zinc-800/15 dark:border-white/10')
|
||||
->add([
|
||||
'[--haze:color-mix(in_oklab,_var(--color-accent-content),_transparent_97.5%)]',
|
||||
'[--haze-border:color-mix(in_oklab,_var(--color-accent-content),_transparent_80%)]',
|
||||
'[--haze-light:color-mix(in_oklab,_var(--color-accent),_transparent_98%)]',
|
||||
'dark:[--haze:color-mix(in_oklab,_var(--color-accent-content),_transparent_90%)]',
|
||||
])
|
||||
->add(match ($accent) {
|
||||
true => [
|
||||
'[&:hover_[data-flux-checkbox-indicator]]:border-[var(--haze-border)] dark:[&:hover_[data-flux-checkbox-indicator]]:border-white/10',
|
||||
'hover:border-[var(--haze-border)] dark:hover:border-white/10',
|
||||
|
||||
'data-checked:border-(--color-accent) hover:data-checked:border-(--color-accent) dark:data-checked:bg-white/15 ',
|
||||
'hover:after:bg-[var(--haze-light)] dark:hover:after:bg-white/[4%] data-checked:after:bg-(--haze) hover:data-checked:after:bg-(--haze)',
|
||||
],
|
||||
false => [
|
||||
'data-checked:bg-zinc-50 dark:data-checked:bg-white/15 data-checked:border-zinc-800 dark:data-checked:border-white',
|
||||
'hover:bg-zinc-50 dark:hover:bg-white/15',
|
||||
],
|
||||
})
|
||||
->add('[&[disabled]]:opacity-50 dark:[&[disabled]]:opacity-75 [&[disabled]]:cursor-default [&[disabled]]:pointer-events-none')
|
||||
;
|
||||
@endphp
|
||||
|
||||
{{-- We have to put tabindex="-1" here because otherwise, Livewire requests will wipe out tabindex state, --}}
|
||||
{{-- even with durable attributes for some reason... --}}
|
||||
{{-- We have to put "data-flux-field" so that a single box can be disabled without "disabling" the group field label... --}}
|
||||
<ui-checkbox {{ $attributes->class($classes) }} data-flux-control data-flux-checkbox-cards tabindex="-1" data-flux-field>
|
||||
<?php if ($label): ?>
|
||||
<div class="flex-1 flex gap-2">
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<flux:icon :icon="$icon" :variant="$iconVariant" :class="$iconClasses" />
|
||||
<?php elseif ($icon): ?>
|
||||
{{ $icon }}
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="flex-1">
|
||||
<flux:heading>{{ $label ?? $slot }}</flux:heading>
|
||||
|
||||
<?php if ($description): ?>
|
||||
<flux:subheading size="sm">{{ $description }}</flux:subheading>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<flux:checkbox.indicator />
|
||||
<?php else: ?>
|
||||
{{ $slot }}
|
||||
<?php endif; ?>
|
||||
</ui-checkbox>
|
||||
25
resources/views/flux/checkbox/variants/default.blade.php
Normal file
25
resources/views/flux/checkbox/variants/default.blade.php
Normal file
@@ -0,0 +1,25 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'name' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
// We only want to show the name attribute on the checkbox if it has been set
|
||||
// manually, but not if it has been set from the wire:model attribute...
|
||||
$showName = isset($name);
|
||||
|
||||
if (! isset($name)) {
|
||||
$name = $attributes->whereStartsWith('wire:model')->first();
|
||||
}
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('flex size-[1.125rem] rounded-[.3rem] mt-px outline-offset-2')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<flux:with-inline-field :$attributes>
|
||||
<ui-checkbox {{ $attributes->class($classes) }} @if($showName) name="{{ $name }}" @endif data-flux-control data-flux-checkbox>
|
||||
<flux:checkbox.indicator />
|
||||
</ui-checkbox>
|
||||
</flux:with-inline-field>
|
||||
29
resources/views/flux/checkbox/variants/pills.blade.php
Normal file
29
resources/views/flux/checkbox/variants/pills.blade.php
Normal file
@@ -0,0 +1,29 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'accent' => true,
|
||||
'label' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('flex whitespace-nowrap gap-2 items-center py-1 px-2 rounded-full text-sm font-medium leading-4')
|
||||
->add('bg-zinc-800/6 dark:bg-white/10 hover:bg-zinc-800/10 dark:hover:bg-white/15 text-zinc-800 hover:text-zinc-800 dark:text-white/70 dark:hover:text-white')
|
||||
->add(match ($accent) {
|
||||
true => 'data-checked:bg-(--color-accent) hover:data-checked:bg-(--color-accent)',
|
||||
false => 'data-checked:bg-zinc-800 dark:data-checked:bg-white',
|
||||
})
|
||||
->add(match ($accent) {
|
||||
true => 'data-checked:text-(--color-accent-foreground) hover:data-checked:text-(--color-accent-foreground)',
|
||||
false => 'data-checked:text-white dark:data-checked:text-zinc-800',
|
||||
})
|
||||
->add('[&[disabled]]:opacity-50 dark:[&[disabled]]:opacity-75 [&[disabled]]:cursor-default [&[disabled]]:pointer-events-none')
|
||||
;
|
||||
@endphp
|
||||
|
||||
{{-- We have to put tabindex="-1" here because otherwise, Livewire requests will wipe out tabindex state, --}}
|
||||
{{-- even with durable attributes for some reason... --}}
|
||||
{{-- We have to put "data-flux-field" so that a single box can be disabled without "disabling" the group field label... --}}
|
||||
<ui-checkbox {{ $attributes->class($classes) }} data-flux-control data-flux-checkbox-pills tabindex="-1" data-flux-field>
|
||||
{{ $label ?? $slot }}
|
||||
</ui-checkbox>
|
||||
9
resources/views/flux/command/empty.blade.php
Normal file
9
resources/views/flux/command/empty.blade.php
Normal file
@@ -0,0 +1,9 @@
|
||||
@blaze
|
||||
|
||||
<ui-option-empty class="data-hidden:hidden">
|
||||
<div class="flex items-center justify-center h-10">
|
||||
<div class="text-sm text-zinc-500 dark:text-zinc-400 font-medium">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
</ui-option-empty>
|
||||
16
resources/views/flux/command/index.blade.php
Normal file
16
resources/views/flux/command/index.blade.php
Normal file
@@ -0,0 +1,16 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'placeholder' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('w-full block rounded-xl overflow-hidden shadow-xs')
|
||||
->add('border border-zinc-200 dark:border-zinc-600')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<ui-select clear="action" {{ $attributes->class($classes)->merge(['filter' => true]) }} data-flux-command>
|
||||
{{ $slot }}
|
||||
</ui-select>
|
||||
51
resources/views/flux/command/input.blade.php
Normal file
51
resources/views/flux/command/input.blade.php
Normal file
@@ -0,0 +1,51 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'clearable' => null,
|
||||
'closable' => null,
|
||||
'icon' => 'magnifying-glass',
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('h-12 w-full flex items-center px-3 py-2')
|
||||
->add('font-medium text-base sm:text-sm text-zinc-800 dark:text-white')
|
||||
->add('ps-11') // Make room for magnifying glass icon...
|
||||
->add(($closable || $clearable) ? 'pe-11' : '') // Make room for close/clear button...
|
||||
->add('outline-hidden')
|
||||
->add('border-b border-zinc-200 dark:border-zinc-600')
|
||||
->add('bg-white dark:bg-zinc-700')
|
||||
// The below reverts styles added by Tailwind Forms plugin
|
||||
->add('border-t-0 border-s-0 border-e-0 focus:ring-0 focus:border-zinc-200 dark:focus:border-zinc-600')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div class="relative" data-flux-command-input>
|
||||
<div class="absolute top-0 bottom-0 flex items-center justify-center text-xs text-zinc-400 ps-3.5 start-0 [&:has(+input:focus)]:text-zinc-800 dark:[&:has(+input:focus)]:text-zinc-400">
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<flux:icon :$icon variant="mini" />
|
||||
<?php else: ?>
|
||||
{{ $icon }}
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<input type="text" {{ $attributes->class($classes) }} />
|
||||
|
||||
<?php if ($closable): ?>
|
||||
<div class="absolute top-0 bottom-0 flex items-center justify-center pe-2 end-0">
|
||||
<ui-close>
|
||||
<flux:button square variant="subtle" size="sm" aria-label="Close command modal">
|
||||
<flux:icon.x-mark variant="micro" />
|
||||
</flux:button>
|
||||
</ui-close>
|
||||
</div>
|
||||
<?php elseif ($clearable): ?>
|
||||
<div class="absolute top-0 bottom-0 flex items-center justify-center pe-2 end-0 [[data-flux-command-input]:has(input:placeholder-shown)_&]:hidden">
|
||||
<flux:button square variant="subtle" size="sm" tabindex="-1" aria-label="Clear command input"
|
||||
x-on:click="$el.closest('[data-flux-command-input]').querySelector('input').value = ''; $el.closest('[data-flux-command-input]').querySelector('input').dispatchEvent(new Event('input', { bubbles: false })); $el.closest('[data-flux-command-input]').querySelector('input').focus()"
|
||||
>
|
||||
<flux:icon.x-mark variant="micro" />
|
||||
</flux:button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
38
resources/views/flux/command/item.blade.php
Normal file
38
resources/views/flux/command/item.blade.php
Normal file
@@ -0,0 +1,38 @@
|
||||
@blaze
|
||||
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'iconVariant' => 'outline',
|
||||
'icon' => null,
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('w-full group/item data-hidden:hidden h-10 flex items-center px-2 py-1.5 focus:outline-hidden')
|
||||
->add('rounded-md')
|
||||
->add('text-start text-sm font-medium')
|
||||
->add('text-zinc-800 data-active:bg-zinc-100 dark:text-white dark:data-active:bg-zinc-600')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<ui-option action {{ $attributes->class($classes) }} data-flux-command-item>
|
||||
<?php if ($icon): ?>
|
||||
<div class="relative">
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<flux:icon :$icon :variant="$iconVariant" class="me-2 size-6 text-zinc-400 dark:text-zinc-400 group-data-active/item:text-zinc-800 dark:group-data-active/item:text-white" />
|
||||
<?php else: ?>
|
||||
{{ $icon }}
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
{{ $slot }}
|
||||
|
||||
<?php if ($kbd): ?>
|
||||
<div class="inline-flex ms-auto rounded-sm bg-zinc-800/5 dark:bg-white/10 px-1 py-0.5">
|
||||
<span class="font-medium text-xs text-zinc-500 dark:text-zinc-300">{{ $kbd }}</span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</ui-option>
|
||||
15
resources/views/flux/command/items.blade.php
Normal file
15
resources/views/flux/command/items.blade.php
Normal file
@@ -0,0 +1,15 @@
|
||||
@blaze
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('p-[.3125rem]')
|
||||
->add('overflow-y-auto')
|
||||
->add('bg-white dark:bg-zinc-700')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<ui-options {{ $attributes->class($classes) }} data-flux-command-items>
|
||||
{{ $slot }}
|
||||
|
||||
<flux:command.empty>{!! __('No results found') !!}</flux:command.empty>
|
||||
</ui-options>
|
||||
77
resources/views/flux/composer/index.blade.php
Normal file
77
resources/views/flux/composer/index.blade.php
Normal file
@@ -0,0 +1,77 @@
|
||||
@props([
|
||||
'name' => $attributes->whereStartsWith('wire:model')->first(),
|
||||
'actionsTrailing' => null,
|
||||
'actionsLeading' => null,
|
||||
'variant' => null,
|
||||
'invalid' => null,
|
||||
'footer' => null,
|
||||
'header' => null,
|
||||
'input' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$invalid ??= ($name && $errors->has($name));
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('w-full p-2')
|
||||
->add('grid grid-cols-[auto_1fr_1fr_auto]')
|
||||
->add('shadow-xs [&:has([disabled])]:shadow-none border')
|
||||
->add('bg-white dark:bg-white/10 dark:[&:has([disabled])]:bg-white/[7%]')
|
||||
->add(match ($variant) {
|
||||
'input' => 'rounded-lg',
|
||||
default => 'rounded-2xl [&_[data-flux-button]]:rounded-lg',
|
||||
})
|
||||
->add($invalid ? 'border-red-500' : 'border-zinc-200 border-b-zinc-300/80 dark:border-white/10')
|
||||
;
|
||||
|
||||
$textareaClasses = Flux::classes()
|
||||
->add('block w-full resize-none px-2 py-1.5')
|
||||
->add('outline-none!')
|
||||
->add('text-base sm:text-sm text-zinc-700 [[disabled]_&]:text-zinc-500 placeholder-zinc-400 [[disabled]_&]:placeholder-zinc-400/70 dark:text-zinc-300 dark:[[disabled]_&]:text-zinc-400 dark:placeholder-zinc-400 dark:[[disabled]_&]:placeholder-zinc-500')
|
||||
;
|
||||
|
||||
// Support adding the .self modifier to the wire:model directive...
|
||||
if (($wireModel = $attributes->wire('model')) && $wireModel->directive && ! $wireModel->hasModifier('self')) {
|
||||
unset($attributes[$wireModel->directive]);
|
||||
|
||||
$wireModel->directive .= '.self';
|
||||
|
||||
$attributes = $attributes->merge([$wireModel->directive => $wireModel->value]);
|
||||
}
|
||||
@endphp
|
||||
|
||||
<flux:with-field :$attributes :$name>
|
||||
<ui-composer {{ $attributes->class($classes) }} data-flux-composer>
|
||||
<?php if ($header): ?>
|
||||
<div {{ $header->attributes->class('col-span-3 flex items-center gap-1 mb-2') }}>
|
||||
{{ $header }}
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="col-span-4 [[inline]_&]:col-span-2 [[inline]_&]:col-start-2">
|
||||
<?php if ($input): ?>
|
||||
{{ $input }}
|
||||
<?php else: ?>
|
||||
<textarea class="{{ $textareaClasses }}"></textarea>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php if ($actionsLeading): ?>
|
||||
<div {{ $actionsLeading->attributes->class('col-span-2 [[inline]_&]:col-span-1 [[inline]_&]:col-start-1 [[inline]_&]:row-start-1 flex items-start gap-1') }}>
|
||||
{{ $actionsLeading }}
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($actionsTrailing): ?>
|
||||
<div {{ $actionsTrailing->attributes->class('col-span-2 [[inline]_&]:col-span-1 flex items-start justify-end gap-1') }}>
|
||||
{{ $actionsTrailing }}
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($footer): ?>
|
||||
<div {{ $footer->attributes->class('col-span-4 flex items-center gap-1') }}>
|
||||
{{ $footer }}
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</ui-composer>
|
||||
</flux:with-field>
|
||||
11
resources/views/flux/container.blade.php
Normal file
11
resources/views/flux/container.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('mx-auto w-full [:where(&)]:max-w-7xl px-6 lg:px-8')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<div {{ $attributes->class($classes) }} data-flux-container>
|
||||
{{ $slot }}
|
||||
</div>
|
||||
20
resources/views/flux/context.blade.php
Normal file
20
resources/views/flux/context.blade.php
Normal file
@@ -0,0 +1,20 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'position' => 'bottom end',
|
||||
])
|
||||
|
||||
@php
|
||||
// Support adding the .self modifier to the wire:model directive...
|
||||
if (($wireModel = $attributes->wire('model')) && $wireModel->directive && ! $wireModel->hasModifier('self')) {
|
||||
unset($attributes[$wireModel->directive]);
|
||||
|
||||
$wireModel->directive .= '.self';
|
||||
|
||||
$attributes = $attributes->merge([$wireModel->directive => $wireModel->value]);
|
||||
}
|
||||
@endphp
|
||||
|
||||
<ui-context position="{{ $position }}" {{ $attributes }} data-flux-context>
|
||||
{{ $slot }}
|
||||
</ui-context>
|
||||
56
resources/views/flux/date-picker/button.blade.php
Normal file
56
resources/views/flux/date-picker/button.blade.php
Normal file
@@ -0,0 +1,56 @@
|
||||
@aware([ 'placeholder' ])
|
||||
|
||||
@props([
|
||||
'placeholder' => null,
|
||||
'clearable' => null,
|
||||
'invalid' => false,
|
||||
'size' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('group/select-button cursor-default py-2')
|
||||
->add('overflow-hidden') // Overflow hidden is here to prevent the button from growing if the selected date text is too long.
|
||||
->add('flex items-center')
|
||||
->add('shadow-xs')
|
||||
->add('bg-white dark:bg-white/10 dark:disabled:bg-white/[7%]')
|
||||
// Make the placeholder match the text color of standard input placeholders...
|
||||
->add('disabled:shadow-none')
|
||||
->add(match ($size) {
|
||||
default => 'h-10 text-base sm:text-sm rounded-lg px-3 block w-full',
|
||||
'sm' => 'h-8 text-sm rounded-lg ps-3 pe-2 block w-full',
|
||||
'xs' => 'h-6 text-xs rounded-lg ps-3 pe-2 block w-full',
|
||||
})
|
||||
->add($invalid
|
||||
? 'border border-red-500'
|
||||
: 'border border-zinc-200 border-b-zinc-300/80 dark:border-white/10'
|
||||
)
|
||||
;
|
||||
@endphp
|
||||
|
||||
<button type="button" {{ $attributes->class($classes) }} @if ($invalid) data-invalid @endif data-flux-group-target data-flux-date-picker-button>
|
||||
<flux:icon.calendar variant="mini" class="me-2 text-zinc-400/75 [[disabled]_&]:text-zinc-200! dark:text-white/60 dark:[[disabled]_&]:text-white/40!" />
|
||||
|
||||
<?php if ($slot->isNotEmpty()): ?>
|
||||
{{ $slot }}
|
||||
<?php else: ?>
|
||||
<flux:date-picker.selected :$placeholder />
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($clearable): ?>
|
||||
<flux:button as="div"
|
||||
class="cursor-pointer ms-2 {{ $size === 'sm' || $size === 'xs' ? '-me-1' : '-me-2' }} [[data-flux-date-picker-button]:has([data-flux-date-picker-placeholder])_&]:hidden [[data-flux-select]:has([disabled])_&]:hidden"
|
||||
variant="subtle"
|
||||
:size="$size === 'sm' || $size === 'xs' ? 'xs' : 'sm'"
|
||||
square
|
||||
tabindex="-1"
|
||||
aria-label="Clear date"
|
||||
x-on:click.prevent.stop="let datePicker = $el.closest('ui-date-picker'); datePicker.clear();"
|
||||
>
|
||||
<flux:icon.x-mark variant="micro" />
|
||||
</flux:button>
|
||||
<?php endif; ?>
|
||||
|
||||
<flux:icon.chevron-down variant="mini" class="ms-2 -me-1 text-zinc-400/75 [[data-flux-date-picker-button]:hover_&]:text-zinc-800 [[disabled]_&]:text-zinc-200! dark:text-white/60 dark:[[data-flux-date-picker-button]:hover_&]:text-white dark:[[disabled]_&]:text-white/40!" />
|
||||
</button>
|
||||
297
resources/views/flux/date-picker/index.blade.php
Normal file
297
resources/views/flux/date-picker/index.blade.php
Normal file
@@ -0,0 +1,297 @@
|
||||
@props([
|
||||
'selectableHeader' => null,
|
||||
'withConfirmation' => null,
|
||||
'weekNumbers' => null,
|
||||
'placeholder' => null,
|
||||
'withPresets' => null,
|
||||
'unavailable' => null,
|
||||
'withInputs' => null,
|
||||
'clearable' => null,
|
||||
'withToday' => null,
|
||||
'type' => 'button',
|
||||
'presets' => null,
|
||||
'trigger' => null,
|
||||
'invalid' => null,
|
||||
'months' => null,
|
||||
'value' => null,
|
||||
'size' => null,
|
||||
'name' => null,
|
||||
'mode' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
// We only want to show the name attribute if it has been set manually
|
||||
// but not if it has been set from the `wire:model` attribute...
|
||||
$showName = isset($name);
|
||||
if (! isset($name)) {
|
||||
$name = $attributes->whereStartsWith('wire:model')->first();
|
||||
}
|
||||
|
||||
// Support adding the .self modifier to the wire:model directive...
|
||||
if (($wireModel = $attributes->wire('model')) && $wireModel->directive && ! $wireModel->hasModifier('self')) {
|
||||
unset($attributes[$wireModel->directive]);
|
||||
|
||||
$wireModel->directive .= '.self';
|
||||
|
||||
$attributes = $attributes->merge([$wireModel->directive => $wireModel->value]);
|
||||
}
|
||||
|
||||
$months = $months ?? ($mode === 'range' ? 2 : 1);
|
||||
|
||||
$range = $mode === 'range';
|
||||
|
||||
$placeholder = $placeholder ?? ($range ? __('Select a date range') : __('Select a date'));
|
||||
|
||||
// Mark it invalid if the property or any of it's nested attributes have errors...
|
||||
$invalid ??= ($name && ($errors->has($name) || $errors->has($name . '.*')));
|
||||
|
||||
$class = Flux::classes()
|
||||
->add('block min-w-0')
|
||||
// The below reverts styles added by Tailwind Forms plugin...
|
||||
->add('border-0 p-0 bg-transparent')
|
||||
;
|
||||
|
||||
$sizeClasses = match ($size) {
|
||||
'2xl' => $weekNumbers ? 'size-11 sm:size-14' : 'size-12 sm:size-12',
|
||||
'xl' => $weekNumbers ? 'size-11 sm:size-12' : 'size-12 sm:size-12',
|
||||
'lg' => $weekNumbers ? 'size-10 sm:size-11' : 'size-11 sm:size-11',
|
||||
default => $weekNumbers ? 'size-10 sm:size-10' : 'size-11 sm:size-10',
|
||||
'sm' => $weekNumbers ? 'size-10 sm:size-9' : 'size-11 sm:size-9',
|
||||
};
|
||||
|
||||
if ($withPresets) {
|
||||
$presets = $presets ?? 'today yesterday thisWeek last7Days thisMonth yearToDate allTime';
|
||||
}
|
||||
|
||||
$presetArrayOfStrings = (string) is_string($presets) ? explode(' ', $presets) : [];
|
||||
|
||||
$presetArray = array_map(function ($preset) {
|
||||
return Flux\DateRangePreset::from($preset);
|
||||
}, $presetArrayOfStrings);
|
||||
|
||||
// Add support for `$value` being an array, if for example it's coming from
|
||||
// the `old()` helper or if a user prefers to pass data in as an array...
|
||||
if (is_array($value)) {
|
||||
$value = match (true) {
|
||||
$mode === 'range' => isset($value['start']) && isset($value['end']) ? $value['start'] . '/' . $value['end'] : null,
|
||||
default => collect($value)->join(','),
|
||||
};
|
||||
}
|
||||
|
||||
if (isset($unavailable)) {
|
||||
$unavailable = collect($unavailable)->implode(',');
|
||||
}
|
||||
@endphp
|
||||
|
||||
<flux:with-field :$attributes :$name>
|
||||
<ui-date-picker
|
||||
{{ $attributes->class($class) }}
|
||||
data-flux-control
|
||||
data-flux-date-picker
|
||||
@if ($mode) mode="{{ $mode }}" @endif
|
||||
months="1"
|
||||
sm:months="{{ $months }}"
|
||||
@if (isset($unavailable) && $unavailable !== '') unavailable="{{ $unavailable }}" @endif
|
||||
@if ($showName) name="{{ $name }}" @endif
|
||||
@if (isset($value)) value="{{ $value }}" @endif
|
||||
>
|
||||
<?php if ($trigger === null): ?>
|
||||
<?php if ($type === 'input'): ?>
|
||||
<flux:date-picker.input :$placeholder :$invalid :$size :$clearable />
|
||||
<?php else: ?>
|
||||
<flux:date-picker.button :$placeholder :$invalid :$size :$clearable />
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
{{ $trigger }}
|
||||
<?php endif; ?>
|
||||
|
||||
<dialog wire:ignore class="max-sm:max-h-full! rounded-xl shadow-xl sm:shadow-2xs max-sm:fixed! max-sm:inset-0! sm:backdrop:bg-transparent bg-white dark:bg-zinc-900 sm:border border-zinc-200 dark:border-white/10">
|
||||
<ui-calendar class="isolate relative grid sm:grid-cols-[auto_1fr] grid-rows-[auto_auto_auto_auto_auto]" wire:ignore>
|
||||
<?php if ($presets): ?>
|
||||
<ui-calendar-presets class="row-span-full max-sm:hidden border-e border-zinc-200 dark:border-zinc-600">
|
||||
<ui-radio-group class="flex flex-col gap-1 p-2 min-w-[120px]">
|
||||
@foreach ($presetArray as $preset)
|
||||
<ui-radio
|
||||
value="{{ $preset->value }}"
|
||||
class="text-sm font-medium text-zinc-600 dark:text-zinc-300 data-checked:bg-(--color-accent) data-checked:text-(--color-accent-foreground) px-2 py-1.5 whitespace-nowrap rounded-lg hover:bg-zinc-100 hover:text-zinc-800 dark:hover:bg-white/5 dark:hover:text-white"
|
||||
>{{ $preset->label() }}</ui-radio>
|
||||
@endforeach
|
||||
</ui-radio-group>
|
||||
</ui-calendar-presets>
|
||||
<?php else: ?>
|
||||
<div class="row-span-full"></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($withInputs): ?>
|
||||
<ui-calendar-inputs class="flex items-center p-2 border-b border-zinc-200 dark:border-white/10">
|
||||
<?php if ($range): ?>
|
||||
<div class="sm:px-2 flex items-center gap-4">
|
||||
<div class="flex items-center gap-2"><span class="max-sm:hidden text-sm font-medium text-zinc-800 dark:text-white">{{ __('Start') }}</span> <flux:input type="date" class="w-[full] sm:w-[11.25rem]" /></div>
|
||||
<div class="flex items-center gap-2"><span class="max-sm:hidden text-sm font-medium text-zinc-800 dark:text-white">{{ __('End') }}</span> <flux:input type="date" class="w-[full] sm:w-[11.25rem]" /></div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<flux:input type="date" class="w-full sm:w-[11.25rem]" />
|
||||
<?php endif; ?>
|
||||
</ui-calendar-inputs>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="relative">
|
||||
<div class="z-10 absolute top-0 inset-x-0 p-2">
|
||||
<header class="flex justify-between items-center">
|
||||
<div class="flex items-center gap-2">
|
||||
<?php if ($selectableHeader): ?>
|
||||
<ui-calendar-month display="short" class="font-medium text-sm text-zinc-800 dark:text-white">
|
||||
<select
|
||||
class="h-10 py-0 border-0 text-sm sm:h-8 appearance-none rounded-lg bg-zinc-100 dark:bg-white/10 dark:[&>option]:bg-zinc-700 dark:[&>option]:text-white px-3 sm:ps-2 [background-position:_right_.25rem_center_!important] rtl:[background-position:_left_.25rem_center_!important] pe-[1.35rem] bg-[length:16px_16px] bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%2300000040%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] hover:bg-[length:16px_16px] hover:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%231f2937%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] dark:bg-[length:16px_16px] dark:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%23ffffff75%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] dark:hover:bg-[length:16px_16px] dark:hover:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%23ffffff%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] bg-no-repeat"
|
||||
>
|
||||
<template>
|
||||
<option><slot></slot></option>
|
||||
</template>
|
||||
</select>
|
||||
</ui-calendar-month>
|
||||
|
||||
<ui-calendar-year class="font-medium text-sm text-zinc-800 dark:text-white">
|
||||
<select
|
||||
class="h-10 py-0 border-0 text-sm sm:h-8 appearance-none rounded-lg bg-zinc-100 dark:bg-white/10 dark:[&>option]:bg-zinc-700 dark:[&>option]:text-white px-3 sm:ps-2 [background-position:_right_.25rem_center_!important] rtl:[background-position:_left_.25rem_center_!important] pe-[1.35rem] bg-[length:16px_16px] bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%2300000040%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] hover:bg-[length:16px_16px] hover:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%231f2937%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] dark:bg-[length:16px_16px] dark:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%23ffffff75%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] dark:hover:bg-[length:16px_16px] dark:hover:bg-[url('data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%2016%2016%22%20fill=%22%23ffffff%22%20class=%22size-4%22%3E%3Cpath%20fill-rule=%22evenodd%22%20d=%22M4.22%206.22a.75.75%200%200%201%201.06%200L8%208.94l2.72-2.72a.75.75%200%201%201%201.06%201.06l-3.25%203.25a.75.75%200%200%201-1.06%200L4.22%207.28a.75.75%200%200%201%200-1.06Z%22%20clip-rule=%22evenodd%22/%3E%3C/svg%3E')] bg-no-repeat"
|
||||
>
|
||||
<template>
|
||||
<option><slot></slot></option>
|
||||
</template>
|
||||
</select>
|
||||
</ui-calendar-year>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<?php if ($withToday): ?>
|
||||
<ui-calendar-today class="size-10 sm:size-8 rounded-lg flex items-center justify-center text-zinc-400 hover:bg-zinc-100 hover:text-zinc-800 dark:hover:bg-white/5 dark:hover:text-white [&[disabled]]:opacity-50 [&[disabled]]:pointer-events-none" aria-label="Previous month">
|
||||
<div class="relative">
|
||||
<template name="today">
|
||||
<div class="cursor-default absolute inset-0 mt-[3px] flex items-center justify-center text-[.5625rem] font-semibold"><slot></slot></div>
|
||||
</template>
|
||||
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.75 2C5.94891 2 6.13968 2.07902 6.28033 2.21967C6.42098 2.36032 6.5 2.55109 6.5 2.75V4H13.5V2.75C13.5 2.55109 13.579 2.36032 13.7197 2.21967C13.8603 2.07902 14.0511 2 14.25 2C14.4489 2 14.6397 2.07902 14.7803 2.21967C14.921 2.36032 15 2.55109 15 2.75V4H15.25C15.9793 4 16.6788 4.28973 17.1945 4.80546C17.7103 5.32118 18 6.02065 18 6.75V15.25C18 15.9793 17.7103 16.6788 17.1945 17.1945C16.6788 17.7103 15.9793 18 15.25 18H4.75C4.02065 18 3.32118 17.7103 2.80546 17.1945C2.28973 16.6788 2 15.9793 2 15.25V6.75C2 6.02065 2.28973 5.32118 2.80546 4.80546C3.32118 4.28973 4.02065 4 4.75 4H5V2.75C5 2.55109 5.07902 2.36032 5.21967 2.21967C5.36032 2.07902 5.55109 2 5.75 2ZM4.75 6.5C4.06 6.5 3.5 7.06 3.5 7.75V15.25C3.5 15.94 4.06 16.5 4.75 16.5H15.25C15.94 16.5 16.5 15.94 16.5 15.25V7.75C16.5 7.06 15.94 6.5 15.25 6.5H4.75Z" fill="currentColor"/>
|
||||
</svg>
|
||||
</div>
|
||||
</ui-calendar-today>
|
||||
<?php endif; ?>
|
||||
|
||||
<ui-calendar-previous class="size-10 sm:size-8 rounded-lg flex items-center justify-center text-zinc-400 hover:bg-zinc-100 hover:text-zinc-800 dark:hover:bg-white/5 dark:hover:text-white [&[disabled]]:opacity-50 [&[disabled]]:pointer-events-none" aria-label="Previous month">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 rtl:hidden"> <path fill-rule="evenodd" d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" /> </svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 hidden rtl:block"> <path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /> </svg>
|
||||
</ui-calendar-previous>
|
||||
|
||||
<ui-calendar-next class="size-10 sm:size-8 rounded-lg flex items-center justify-center text-zinc-400 hover:bg-zinc-100 hover:text-zinc-800 dark:hover:bg-white/5 dark:hover:text-white [&[disabled]]:opacity-50 [&[disabled]]:pointer-events-none [&[disabled]_&]:text-zinc-400" aria-label="Next month">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 rtl:hidden"> <path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /> </svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 hidden rtl:block"> <path fill-rule="evenodd" d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" /> </svg>
|
||||
</ui-calendar-next>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ui-calendar-months class="relative flex justify-center p-2 gap-4">
|
||||
<template name="month">
|
||||
<div>
|
||||
<template name="heading">
|
||||
<div class="@if ($selectableHeader) [[data-month]:first-of-type_&]:opacity-0 @endif mb-2 px-2 h-10 sm:h-8 flex items-center">
|
||||
<div class="font-medium text-sm text-zinc-800 dark:text-white"><slot></slot></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="flex w-full">
|
||||
<?php if ($weekNumbers): ?>
|
||||
<th scope="col" class="{{ $sizeClasses }} text-sm font-medium text-zinc-500 dark:text-zinc-300 flex items-center"><div class="w-full">#</div></th>
|
||||
<?php endif; ?>
|
||||
|
||||
<template name="weekday">
|
||||
<th scope="col" class="{{ $sizeClasses }} text-sm font-medium text-zinc-500 dark:text-zinc-300 flex items-center"><div class="w-full"><slot></slot></div></th>
|
||||
</template>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<template name="week">
|
||||
<tr class="flex w-full not-first-of-type:mt-1 [&:first-of-type_td[data-in-range]:not([data-selected]):first-child]:rounded-s-none [&:last-of-type_td[data-in-range]:not([data-selected]):last-child]:rounded-e-none">
|
||||
<?php if ($weekNumbers): ?>
|
||||
<template name="number">
|
||||
<td class="p-0 relative {{ $sizeClasses }} text-xs font-medium text-zinc-400 flex items-center justify-center">
|
||||
<slot></slot>
|
||||
</td>
|
||||
</template>
|
||||
<?php endif; ?>
|
||||
<template name="day">
|
||||
<?php if ($attributes->has('static')): ?>
|
||||
<td class="p-0 data-unavailable:line-through data-in-range:bg-zinc-100 dark:data-in-range:bg-white/10 data-start:rounded-s-lg data-end:rounded-e-lg data-end-preview:rounded-e-lg first-of-type:rounded-s-lg last-of-type:rounded-e-lg [&[data-selected]+[data-selected]]:rounded-s-none">
|
||||
<div class="relative {{ $sizeClasses }} text-sm font-medium text-zinc-800 dark:text-white flex items-center justify-center rounded-lg [td[data-selected]:has(+td[data-selected])_&]:rounded-e-none [td[data-selected]+td[data-selected]_&]:rounded-s-none [td[data-selected]_&]:bg-[var(--color-accent)] [td[data-selected]_&]:text-[var(--color-accent-foreground)] [td[data-selected]_&[disabled]]:opacity-50 disabled:text-zinc-400 disabled:pointer-events-none disabled:cursor-default">
|
||||
<div class="absolute inset-0 hidden [td[data-today]_&]:flex justify-center items-end"><div class="mb-1 size-1 rounded-full bg-zinc-800 dark:bg-white [td[data-selected]_&]:bg-white dark:[td[data-selected]_&]:bg-zinc-800"></div></div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</td>
|
||||
<?php else: ?>
|
||||
<td class="_max-sm:data-outside:opacity-0 p-0 data-unavailable:line-through data-in-range:bg-zinc-100 dark:data-in-range:bg-white/10 data-start:rounded-s-lg data-end:rounded-e-lg data-end-preview:rounded-e-lg first-of-type:rounded-s-lg last-of-type:rounded-e-lg [&[data-selected]+[data-selected]]:rounded-s-none [[data-in-range]:not([data-selected]):not([data-end-preview])+&[data-outside]]:bg-linear-to-r [&[data-outside]:has(+[data-in-range])]:bg-linear-to-l data-outside:opacity-50 from-zinc-100 dark:from-white/10 from-1% [&[data-outside]:has(+[data-in-range][data-selected])]:bg-none!">
|
||||
<ui-tooltip position="top">
|
||||
<button type="button" class="{{ $sizeClasses }} text-sm font-medium text-zinc-800 dark:text-white flex flex-col items-center justify-center rounded-lg hover:bg-zinc-800/5 dark:hover:bg-white/5 [td[data-selected]:has(+td[data-selected])_&]:rounded-e-none [td[data-selected]+td[data-selected]_&]:rounded-s-none [td[data-selected]_&]:bg-[var(--color-accent)] [td[data-selected]_&]:text-[var(--color-accent-foreground)] [td[data-selected]_&[disabled]]:opacity-50 disabled:text-zinc-400 disabled:pointer-events-none disabled:cursor-default [[readonly]_&]:pointer-events-none [[readonly]_&]:cursor-default [[readonly]_&]:bg-transparent">
|
||||
<div class="relative">
|
||||
<div class="absolute inset-x-0 bottom-[-3px] hidden [td[data-today]_&]:flex justify-center items-end"><div class="size-1 rounded-full bg-zinc-800 dark:bg-white [td[data-selected]_&]:bg-white dark:[td[data-selected]_&]:bg-zinc-800"></div></div>
|
||||
|
||||
<div><slot></slot></div>
|
||||
|
||||
<template name="subtext">
|
||||
<div class="absolute inset-x-0 bottom-[-1rem] flex justify-center font-medium text-xs text-zinc-400 dark:text-zinc-500 [[data-date-variant='success']_&]:text-lime-600 dark:[[data-date-variant='success']_&]:text-lime-400 [[data-date-variant='warning']_&]:text-yellow-600 dark:[[data-date-variant='warning']_&]:text-yellow-400 [[data-date-variant='danger']_&]:text-rose-500 dark:[[data-date-variant='danger']_&]:text-rose-400">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<template name="details">
|
||||
<div popover="manual" class="relative py-2 px-2.5 rounded-md text-xs text-white font-medium bg-zinc-800 dark:bg-zinc-700 dark:border dark:border-white/10 p-0 overflow-visible">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
</ui-tooltip>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
</template>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
</ui-calendar-months>
|
||||
|
||||
<?php if ($presets): ?>
|
||||
<ui-calendar-presets class="block sm:hidden px-4">
|
||||
<select class="appearance-none w-full ps-3 pe-10 block h-10 py-2 text-sm rounded-lg shadow-2xs border bg-white dark:bg-white/10 dark:disabled:bg-white/[9%] text-zinc-700 dark:text-zinc-300 has-[option.placeholder:checked]:text-zinc-400 dark:has-[option.placeholder:checked]:text-zinc-400 disabled:shadow-none border border-zinc-200 border-b-zinc-300/80 dark:border-white/10" data-flux-control="" data-flux-select-native="" data-flux-group-target="">
|
||||
<option value="" disabled="" selected="" class="placeholder">{{ __('Choose predefined range...') }}</option>
|
||||
@foreach ($presetArray as $preset)
|
||||
<option value="{{ $preset->value }}">{{ $preset->label() }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</ui-calendar-presets>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="@unless ($withConfirmation) sm:hidden @endunless p-4 sm:p-2 flex justify-end gap-2">
|
||||
<ui-close>
|
||||
<flux:button variant="ghost">{{ __('Cancel') }}</flux:button>
|
||||
</ui-close>
|
||||
|
||||
<ui-date-picker-select>
|
||||
<flux:button variant="primary">
|
||||
<?php if ($range): ?>
|
||||
{{ __('Select range') }}
|
||||
<?php else: ?>
|
||||
{{ __('Select date') }}
|
||||
<?php endif; ?>
|
||||
</flux:button>
|
||||
</ui-date-picker-select>
|
||||
</div>
|
||||
</ui-calendar>
|
||||
</dialog>
|
||||
</ui-date-picker>
|
||||
</flux:with-field>
|
||||
27
resources/views/flux/date-picker/input.blade.php
Normal file
27
resources/views/flux/date-picker/input.blade.php
Normal file
@@ -0,0 +1,27 @@
|
||||
@aware([ 'placeholder' ])
|
||||
|
||||
@props([
|
||||
'placeholder' => null,
|
||||
'clearable' => false,
|
||||
'invalid' => null,
|
||||
'size' => null,
|
||||
])
|
||||
|
||||
{{-- For Firefox, we need to reset the inputs padding back to the default as if there is no trailing icon, so the native date input calendar icon is correctly positioned... --}}
|
||||
<flux:input type="date" :$invalid :$size :$placeholder :$attributes class:input="[@supports(-moz-appearance:none)]:pe-3">
|
||||
<x-slot name="iconTrailing">
|
||||
<?php if ($clearable): ?>
|
||||
<div class="absolute top-0 bottom-0 flex items-center justify-center pe-10 end-0">
|
||||
<flux:input.clearable :$size as="div" />
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
{{-- Hide this button on Firefox because we can't get rid of the default date input calendar icon, so hide ours instead... --}}
|
||||
<flux:button size="sm" square variant="subtle" class="-me-2 [@supports(-moz-appearance:none)]:hidden [[disabled]_&]:pointer-events-none [&:hover>*]:text-zinc-800 dark:[&:hover>*]:text-white">
|
||||
<flux:icon.calendar variant="mini" class="text-zinc-300 [[disabled]_&]:text-zinc-200! dark:text-white/60 dark:[[disabled]_&]:text-white/40!" />
|
||||
</flux:button>
|
||||
|
||||
{{-- Show this button only on Firefox as it's a clickable overlay that sits over the top of the default date input calendar icon to display our date picker... --}}
|
||||
<flux:button size="sm" square variant="subtle" class="not-[@supports(-moz-appearance:none)]:hidden absolute! w-6! h-auto! right-3.5 top-2 bottom-2 sm:w-6! sm:right-3 sm:top-2 sm:bottom-2" />
|
||||
</x-slot>
|
||||
</flux:input>
|
||||
17
resources/views/flux/date-picker/selected.blade.php
Normal file
17
resources/views/flux/date-picker/selected.blade.php
Normal file
@@ -0,0 +1,17 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'placeholder' => null,
|
||||
])
|
||||
|
||||
<ui-selected-date x-ignore wire:ignore class="truncate flex gap-2 text-start flex-1 text-zinc-700 [[disabled]_&]:text-zinc-500 dark:text-zinc-300 dark:[[disabled]_&]:text-zinc-400">
|
||||
<template name="placeholder">
|
||||
<span class="text-zinc-400 [[disabled]_&]:text-zinc-400/70 dark:text-zinc-400 dark:[[disabled]_&]:text-zinc-500" data-flux-date-picker-placeholder>
|
||||
{{ $placeholder ?? new Illuminate\Support\HtmlString('<slot></slot>') }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template name="date">
|
||||
<div dir="auto"><slot></slot></div>
|
||||
</template>
|
||||
</ui-selected-date>
|
||||
18
resources/views/flux/description.blade.php
Normal file
18
resources/views/flux/description.blade.php
Normal file
@@ -0,0 +1,18 @@
|
||||
@blaze
|
||||
|
||||
@php $srOnly = $srOnly ??= $attributes->pluck('sr-only'); @endphp
|
||||
|
||||
@props([
|
||||
'srOnly' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('text-sm text-zinc-500 dark:text-white/60')
|
||||
->add($srOnly ? 'sr-only' : '')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<ui-description {{ $attributes->class($classes) }} data-flux-description>
|
||||
{{ $slot }}
|
||||
</ui-description>
|
||||
21
resources/views/flux/dropdown.blade.php
Normal file
21
resources/views/flux/dropdown.blade.php
Normal file
@@ -0,0 +1,21 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'position' => 'bottom',
|
||||
'align' => 'start',
|
||||
])
|
||||
|
||||
@php
|
||||
// Support adding the .self modifier to the wire:model directive...
|
||||
if (($wireModel = $attributes->wire('model')) && $wireModel->directive && ! $wireModel->hasModifier('self')) {
|
||||
unset($attributes[$wireModel->directive]);
|
||||
|
||||
$wireModel->directive .= '.self';
|
||||
|
||||
$attributes = $attributes->merge([$wireModel->directive => $wireModel->value]);
|
||||
}
|
||||
@endphp
|
||||
|
||||
<ui-dropdown position="{{ $position }} {{ $align }}" {{ $attributes }} data-flux-dropdown>
|
||||
{{ $slot }}
|
||||
</ui-dropdown>
|
||||
35
resources/views/flux/editor/align.blade.php
Normal file
35
resources/views/flux/editor/align.blade.php
Normal file
@@ -0,0 +1,35 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
<ui-select data-editor="align" class="relative">
|
||||
<flux:tooltip content="{{ __('Align') }}" :$kbd class="contents">
|
||||
<flux:editor.button>
|
||||
<ui-selected>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true"> <path fill-rule="evenodd" d="M2 4.75A.75.75 0 0 1 2.75 4h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 4.75Zm0 10.5a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5a.75.75 0 0 1-.75-.75ZM2 10a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 10Z" clip-rule="evenodd" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Left') }}</div>
|
||||
</ui-selected>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4" aria-hidden="true"> <path fill-rule="evenodd" d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" /> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
|
||||
<ui-options popover="manual" class="min-w-[10rem] rounded-lg border border-zinc-200 dark:border-zinc-600 bg-white dark:bg-zinc-700 shadow-xs p-[5px]">
|
||||
<flux:editor.option value="left" selected>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true"> <path fill-rule="evenodd" d="M2 4.75A.75.75 0 0 1 2.75 4h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 4.75Zm0 10.5a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5a.75.75 0 0 1-.75-.75ZM2 10a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 10Z" clip-rule="evenodd" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Left') }}</div>
|
||||
</flux:editor.option>
|
||||
|
||||
<flux:editor.option value="center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true"> <path fill-rule="evenodd" d="M2 4.75A.75.75 0 0 1 2.75 4h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 4.75ZM2 10a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 10Zm0 5.25a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1-.75-.75Z" clip-rule="evenodd" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Center') }}</div>
|
||||
</flux:editor.option>
|
||||
|
||||
<flux:editor.option value="right">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true"> <path fill-rule="evenodd" d="M2 4.75A.75.75 0 0 1 2.75 4h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 4.75Zm7 10.5a.75.75 0 0 1 .75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5a.75.75 0 0 1-.75-.75ZM2 10a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75A.75.75 0 0 1 2 10Z" clip-rule="evenodd" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Right') }}</div>
|
||||
</flux:editor.option>
|
||||
</ui-options>
|
||||
</ui-select>
|
||||
11
resources/views/flux/editor/blockquote.blade.php
Normal file
11
resources/views/flux/editor/blockquote.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘+Shift+B',
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Blockquote') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="blockquote">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> <path d="M14.1667 5H2.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M17.5 10H6.66666" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M17.5 15H6.66666" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2.5 10V15" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
11
resources/views/flux/editor/bold.blade.php
Normal file
11
resources/views/flux/editor/bold.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘B',
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Bold') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="bold">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5" aria-hidden="true"> <path fill-rule="evenodd" d="M4 3a1 1 0 0 1 1-1h6a4.5 4.5 0 0 1 3.274 7.587A4.75 4.75 0 0 1 11.25 18H5a1 1 0 0 1-1-1V3Zm2.5 5.5v-4H11a2 2 0 1 1 0 4H6.5Zm0 2.5v4.5h4.75a2.25 2.25 0 0 0 0-4.5H6.5Z" clip-rule="evenodd" /> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
11
resources/views/flux/editor/bullet.blade.php
Normal file
11
resources/views/flux/editor/bullet.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Bullet list') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="bullet">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5" aria-hidden="true"> <path fill-rule="evenodd" d="M6 4.75A.75.75 0 0 1 6.75 4h10.5a.75.75 0 0 1 0 1.5H6.75A.75.75 0 0 1 6 4.75ZM6 10a.75.75 0 0 1 .75-.75h10.5a.75.75 0 0 1 0 1.5H6.75A.75.75 0 0 1 6 10Zm0 5.25a.75.75 0 0 1 .75-.75h10.5a.75.75 0 0 1 0 1.5H6.75a.75.75 0 0 1-.75-.75ZM1.99 4.75a1 1 0 0 1 1-1H3a1 1 0 0 1 1 1v.01a1 1 0 0 1-1 1h-.01a1 1 0 0 1-1-1v-.01ZM1.99 15.25a1 1 0 0 1 1-1H3a1 1 0 0 1 1 1v.01a1 1 0 0 1-1 1h-.01a1 1 0 0 1-1-1v-.01ZM1.99 10a1 1 0 0 1 1-1H3a1 1 0 0 1 1 1v.01a1 1 0 0 1-1 1h-.01a1 1 0 0 1-1-1V10Z" clip-rule="evenodd" /> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
36
resources/views/flux/editor/button.blade.php
Normal file
36
resources/views/flux/editor/button.blade.php
Normal file
@@ -0,0 +1,36 @@
|
||||
@blaze
|
||||
|
||||
@php $iconVariant ??= $attributes->pluck('icon:variant'); @endphp
|
||||
|
||||
@props([
|
||||
'iconVariant' => null,
|
||||
'icon' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$iconClasses = Flux::classes()
|
||||
// When using the outline icon variant, we need to size it down to match the default icon sizes...
|
||||
->add($iconVariant === 'outline' ? ($slot->isEmpty() ? 'size-5' : 'size-4') : '')
|
||||
;
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('p-0.5 flex items-center justify-center text-sm font-medium rounded-sm touch-manipulation')
|
||||
->add('text-zinc-400 data-open:text-zinc-800 hover:text-zinc-800 focus:text-zinc-800 data-match:text-zinc-800')
|
||||
->add('disabled:opacity-75 dark:disabled:opacity-75 disabled:cursor-default disabled:pointer-events-none')
|
||||
->add('dark:text-zinc-400 dark:data-open:text-white dark:hover:text-white dark:focus:text-white dark:data-match:text-white')
|
||||
->add('hover:bg-zinc-200 hover:text-zinc-800')
|
||||
->add('dark:hover:bg-white/10 dark:hover:text-white')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<flux:with-tooltip :$attributes>
|
||||
<button type="button" {{ $attributes->class($classes) }}>
|
||||
<?php if (is_string($icon) && $icon !== ''): ?>
|
||||
<flux:icon :$icon :variant="$iconVariant ?? ($slot->isEmpty() ? 'mini' : 'micro')" :class="$iconClasses" />
|
||||
<?php elseif ($icon): ?>
|
||||
{{ $icon }}
|
||||
<?php endif; ?>
|
||||
|
||||
{{ $slot }}
|
||||
</button>
|
||||
</flux:with-tooltip>
|
||||
11
resources/views/flux/editor/code.blade.php
Normal file
11
resources/views/flux/editor/code.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘E',
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Code') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="code">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5" aria-hidden="true"> <path fill-rule="evenodd" d="M6.28 5.22a.75.75 0 0 1 0 1.06L2.56 10l3.72 3.72a.75.75 0 0 1-1.06 1.06L.97 10.53a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Zm7.44 0a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 0 1-1.06-1.06L17.44 10l-3.72-3.72a.75.75 0 0 1 0-1.06ZM11.377 2.011a.75.75 0 0 1 .612.867l-2.5 14.5a.75.75 0 0 1-1.478-.255l2.5-14.5a.75.75 0 0 1 .866-.612Z" clip-rule="evenodd" /> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
3
resources/views/flux/editor/content.blade.php
Normal file
3
resources/views/flux/editor/content.blade.php
Normal file
@@ -0,0 +1,3 @@
|
||||
@blaze
|
||||
|
||||
<ui-editor-content {{ $attributes }} wire:ignore>{{ $slot }}</ui-editor-content>
|
||||
40
resources/views/flux/editor/heading.blade.php
Normal file
40
resources/views/flux/editor/heading.blade.php
Normal file
@@ -0,0 +1,40 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
<ui-select data-editor="heading" class="relative">
|
||||
<flux:tooltip content="{{ __('Styles') }}" :$kbd class="contents">
|
||||
<flux:editor.button>
|
||||
<ui-selected>
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="size-5 shrink-0" aria-hidden="true"> <path d="M3.33331 5.83398V3.33398H16.6666V5.83398" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M7.5 16.666H12.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M10 3.33398V16.6673" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Text') }}</div>
|
||||
</ui-selected>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4" aria-hidden="true"> <path fill-rule="evenodd" d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" aria-hidden="true" /> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
|
||||
<ui-options popover="manual" aria-label="{{ __('Styles') }}" class="min-w-[10rem] rounded-lg border border-zinc-200 dark:border-zinc-600 bg-white dark:bg-zinc-700 shadow-xs p-[5px]">
|
||||
<flux:editor.option value="paragraph" selected>
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="size-5 shrink-0" aria-hidden="true"> <path d="M3.33331 5.83398V3.33398H16.6666V5.83398" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M7.5 16.666H12.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M10 3.33398V16.6673" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Text') }}</div>
|
||||
</flux:editor.option>
|
||||
|
||||
<flux:editor.option value="heading1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true"> <path fill-rule="evenodd" d="M2.75 4a.75.75 0 0 1 .75.75v4.5h5v-4.5a.75.75 0 0 1 1.5 0v10.5a.75.75 0 0 1-1.5 0v-4.5h-5v4.5a.75.75 0 0 1-1.5 0V4.75A.75.75 0 0 1 2.75 4ZM13 8.75a.75.75 0 0 1 .75-.75h1.75a.75.75 0 0 1 .75.75v5.75h1a.75.75 0 0 1 0 1.5h-3.5a.75.75 0 0 1 0-1.5h1v-5h-1a.75.75 0 0 1-.75-.75Z" clip-rule="evenodd" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Heading 1') }}</div>
|
||||
</flux:editor.option>
|
||||
|
||||
<flux:editor.option value="heading2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true"> <path fill-rule="evenodd" d="M2.75 4a.75.75 0 0 1 .75.75v4.5h5v-4.5a.75.75 0 0 1 1.5 0v10.5a.75.75 0 0 1-1.5 0v-4.5h-5v4.5a.75.75 0 0 1-1.5 0V4.75A.75.75 0 0 1 2.75 4ZM15 9.5c-.729 0-1.445.051-2.146.15a.75.75 0 0 1-.208-1.486 16.887 16.887 0 0 1 3.824-.1c.855.074 1.512.78 1.527 1.637a17.476 17.476 0 0 1-.009.931 1.713 1.713 0 0 1-1.18 1.556l-2.453.818a1.25 1.25 0 0 0-.855 1.185v.309h3.75a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75v-1.059a2.75 2.75 0 0 1 1.88-2.608l2.454-.818c.102-.034.153-.117.155-.188a15.556 15.556 0 0 0 .009-.85.171.171 0 0 0-.158-.169A15.458 15.458 0 0 0 15 9.5Z" clip-rule="evenodd" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Heading 2') }}</div>
|
||||
</flux:editor.option>
|
||||
|
||||
<flux:editor.option value="heading3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5 shrink-0" aria-hidden="true"> <path fill-rule="evenodd" d="M2.75 4a.75.75 0 0 1 .75.75v4.5h5v-4.5a.75.75 0 0 1 1.5 0v10.5a.75.75 0 0 1-1.5 0v-4.5h-5v4.5a.75.75 0 0 1-1.5 0V4.75A.75.75 0 0 1 2.75 4ZM15 9.5c-.73 0-1.448.051-2.15.15a.75.75 0 1 1-.209-1.485 16.886 16.886 0 0 1 3.476-.128c.985.065 1.878.837 1.883 1.932V10a6.75 6.75 0 0 1-.301 2A6.75 6.75 0 0 1 18 14v.031c-.005 1.095-.898 1.867-1.883 1.932a17.018 17.018 0 0 1-3.467-.127.75.75 0 0 1 .209-1.485 15.377 15.377 0 0 0 3.16.115c.308-.02.48-.24.48-.441L16.5 14c0-.431-.052-.85-.15-1.25h-2.6a.75.75 0 0 1 0-1.5h2.6c.098-.4.15-.818.15-1.25v-.024c-.001-.201-.173-.422-.481-.443A15.485 15.485 0 0 0 15 9.5Z" clip-rule="evenodd" /> </svg>
|
||||
<div class="[ui-selected_&]:sr-only">{{ __('Heading 3') }}</div>
|
||||
</flux:editor.option>
|
||||
</ui-options>
|
||||
</ui-select>
|
||||
11
resources/views/flux/editor/highlight.blade.php
Normal file
11
resources/views/flux/editor/highlight.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Highlight') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="highlight">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 11-6 6v3h9l3-3"/><path d="m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4"/></svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
52
resources/views/flux/editor/index.blade.php
Normal file
52
resources/views/flux/editor/index.blade.php
Normal file
@@ -0,0 +1,52 @@
|
||||
@props([
|
||||
'toolbar' => null,
|
||||
'invalid' => null,
|
||||
'variant' => null,
|
||||
'name' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
// We only want to show the name attribute on the checkbox if it has been set
|
||||
// manually, but not if it has been set from the wire:model attribute...
|
||||
$showName = isset($name);
|
||||
|
||||
if (! isset($name)) {
|
||||
$name = $attributes->whereStartsWith('wire:model')->first();
|
||||
}
|
||||
|
||||
$invalid ??= ($name && $errors->has($name));
|
||||
|
||||
$classes = Flux::classes()
|
||||
->add('block w-full')
|
||||
->add(match($variant) {
|
||||
'borderless' => [
|
||||
'**:data-[slot=content]:p-2!',
|
||||
],
|
||||
default => [
|
||||
'shadow-xs [&[disabled]]:shadow-none border rounded-lg',
|
||||
'bg-white dark:bg-white/10 dark:[&[disabled]]:bg-white/[7%]',
|
||||
$invalid ? 'border-red-500' : 'border-zinc-200 border-b-zinc-300/80 dark:border-white/10',
|
||||
],
|
||||
})
|
||||
->add('**:data-[slot=content]:text-base! sm:**:data-[slot=content]:text-sm!')
|
||||
->add('**:data-[slot=content]:text-zinc-700 dark:**:data-[slot=content]:text-zinc-300')
|
||||
->add('[&[disabled]_[data-slot=content]]:text-zinc-500 dark:[&[disabled]_[data-slot=content]]:text-zinc-400')
|
||||
;
|
||||
@endphp
|
||||
|
||||
<flux:with-field :$attributes>
|
||||
<ui-editor {{ $attributes->class($classes) }} @if($showName) name="{{ $name }}" @endif aria-label="{{ __('Rich text editor') }}" data-flux-control data-flux-editor>
|
||||
<?php if ($slot->isEmpty()): ?>
|
||||
<flux:editor.toolbar :items="$toolbar" />
|
||||
|
||||
<flux:editor.content />
|
||||
<?php else: ?>
|
||||
{{ $slot }}
|
||||
<?php endif; ?>
|
||||
</ui-editor>
|
||||
</flux:with-field>
|
||||
|
||||
@assets
|
||||
<flux:editor.scripts />
|
||||
<flux:editor.styles />
|
||||
@endassets
|
||||
11
resources/views/flux/editor/italic.blade.php
Normal file
11
resources/views/flux/editor/italic.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘I',
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Italic') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="italic">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5" aria-hidden="true"> <path fill-rule="evenodd" d="M8 2.75A.75.75 0 0 1 8.75 2h7.5a.75.75 0 0 1 0 1.5h-3.215l-4.483 13h2.698a.75.75 0 0 1 0 1.5h-7.5a.75.75 0 0 1 0-1.5h3.215l4.483-13H8.75A.75.75 0 0 1 8 2.75Z" clip-rule="evenodd" /> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
33
resources/views/flux/editor/link.blade.php
Normal file
33
resources/views/flux/editor/link.blade.php
Normal file
@@ -0,0 +1,33 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘K',
|
||||
])
|
||||
|
||||
<flux:dropdown position="bottom center" data-editor="link" class="contents">
|
||||
<flux:tooltip content="{{ __('Insert link') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-match-target>
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> <path d="M7.49999 14.1673H5.83332C4.72825 14.1673 3.66845 13.7283 2.88704 12.9469C2.10564 12.1655 1.66666 11.1057 1.66666 10.0007C1.66666 8.89558 2.10564 7.83577 2.88704 7.05437C3.66845 6.27297 4.72825 5.83398 5.83332 5.83398H7.49999" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M12.5 5.83398H14.1667C15.2717 5.83398 16.3315 6.27297 17.1129 7.05437C17.8943 7.83577 18.3333 8.89558 18.3333 10.0007C18.3333 11.1057 17.8943 12.1655 17.1129 12.9469C16.3315 13.7283 15.2717 14.1673 14.1667 14.1673H12.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M6.66666 10H13.3333" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
|
||||
<div popover="manual" class="min-w-[360px] p-[5px] rounded-lg border border-zinc-200 dark:border-zinc-600 shadow-xs bg-white dark:bg-zinc-700">
|
||||
<div class="h-8 flex justify-between gap-2 ps-2 pe-1" data-flux-editor-link>
|
||||
<input data-editor="link:url" type="text" form="" placeholder="https://..." class="flex-1 text-base sm:text-sm outline-hidden bg-transparent" autofocus>
|
||||
|
||||
<div class="flex gap-2 items-center">
|
||||
<flux:tooltip content="{{ __('Insert link') }}" class="contents">
|
||||
<button type="button" data-editor="link:insert" class="p-0.5 text-sm font-medium text-zinc-400 rounded-sm [[data-flux-editor-link]:not(:has(input:placeholder-shown))_&:hover]:bg-zinc-200 dark:[[data-flux-editor-link]:not(:has(input:placeholder-shown))_&:hover]:bg-white/10 [[data-flux-editor-link]:not(:has(input:placeholder-shown))_&]:text-zinc-800 dark:[[data-flux-editor-link]:not(:has(input:placeholder-shown))_&]:text-white">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-5 shrink-0" aria-hidden="true"> <path fill-rule="evenodd" d="M19.916 4.626a.75.75 0 0 1 .208 1.04l-9 13.5a.75.75 0 0 1-1.154.114l-6-6a.75.75 0 0 1 1.06-1.06l5.353 5.353 8.493-12.74a.75.75 0 0 1 1.04-.207Z" clip-rule="evenodd" /> </svg> <path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z" clip-rule="evenodd" /> </svg>
|
||||
</button>
|
||||
</flux:tooltip>
|
||||
|
||||
<flux:tooltip content="{{ __('Unlink') }}" class="contents">
|
||||
<button type="button" data-editor="link:unlink" class="p-0.5 text-sm font-medium text-zinc-400 rounded-sm [[data-flux-editor-link]:not(:has(input:placeholder-shown))_&:hover]:bg-zinc-200 dark:[[data-flux-editor-link]:not(:has(input:placeholder-shown))_&:hover]:bg-white/10 [[data-flux-editor-link]:not(:has(input:placeholder-shown))_&]:text-zinc-800 dark:[[data-flux-editor-link]:not(:has(input:placeholder-shown))_&]:text-white">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="size-5 shrink-0" aria-hidden="true"> <g clip-path="url(#clip0_1014_3807)"> <path d="M15.7 10.2082L17.1334 8.78317H17.1167C17.8839 7.9882 18.3042 6.92127 18.2855 5.81664C18.2668 4.71202 17.8104 3.65997 17.0167 2.8915C16.2391 2.14166 15.2011 1.72266 14.1209 1.72266C13.0407 1.72266 12.0026 2.14166 11.225 2.8915L9.79169 4.3165" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M4.30834 9.79102L2.88334 11.216C2.11615 12.011 1.69578 13.0779 1.71453 14.1825C1.73328 15.2872 2.18961 16.3392 2.98334 17.1077C3.76089 17.8575 4.79898 18.2765 5.87918 18.2765C6.95938 18.2765 7.99747 17.8575 8.77501 17.1077L10.2 15.6827" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M6.66669 1.66602V4.16602" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M1.66669 6.66602H4.16669" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M13.3333 15.834V18.334" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M15.8333 13.334H18.3333" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </g> <defs> <clipPath id="clip0_1014_3807"> <rect width="20" height="20" fill="white"/> </clipPath> </defs> </svg>
|
||||
</button>
|
||||
</flux:tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</flux:dropdown>
|
||||
5
resources/views/flux/editor/option.blade.php
Normal file
5
resources/views/flux/editor/option.blade.php
Normal file
@@ -0,0 +1,5 @@
|
||||
@blaze
|
||||
|
||||
<ui-option {{ $attributes }} class="h-8 px-2 flex items-center gap-2 rounded-lg text-sm font-medium text-zinc-800 dark:text-white data-active:bg-zinc-50 dark:data-active:bg-zinc-600 [&>svg]:text-zinc-400 [&[data-active]>svg]:text-zinc-800 dark:[&[data-active]>svg]:text-white">
|
||||
{{ $slot }}
|
||||
</ui-option>
|
||||
11
resources/views/flux/editor/ordered.blade.php
Normal file
11
resources/views/flux/editor/ordered.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Ordered list') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="ordered">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> <path d="M8.33334 10H17.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8.33334 15H17.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8.33334 5H17.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M3.33334 8.33398H5.00001" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M3.33334 5H4.16668V8.33333" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M5.00001 15.0007H3.33334C3.33334 14.1674 5.00001 13.334 5.00001 12.5007C5.00001 11.6674 4.16668 11.2507 3.33334 11.6674" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
11
resources/views/flux/editor/redo.blade.php
Normal file
11
resources/views/flux/editor/redo.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘+Shift+Z',
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Redo') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="redo">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"/></svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
2
resources/views/flux/editor/scripts.blade.php
Normal file
2
resources/views/flux/editor/scripts.blade.php
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
{!! app('flux')->editorScripts() !!}
|
||||
3
resources/views/flux/editor/separator.blade.php
Normal file
3
resources/views/flux/editor/separator.blade.php
Normal file
@@ -0,0 +1,3 @@
|
||||
@blaze
|
||||
|
||||
<div data-orientation="vertical" role="none" class="h-4 border-0 bg-zinc-200 dark:bg-white/20 w-px"></div>
|
||||
3
resources/views/flux/editor/spacer.blade.php
Normal file
3
resources/views/flux/editor/spacer.blade.php
Normal file
@@ -0,0 +1,3 @@
|
||||
@blaze
|
||||
|
||||
<div class="flex-1" role="none"></div>
|
||||
11
resources/views/flux/editor/strike.blade.php
Normal file
11
resources/views/flux/editor/strike.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘+Shift+S',
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Strikethrough') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="strike">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5" aria-hidden="true"> <path fill-rule="evenodd" d="M11.617 3.963c-1.186-.318-2.418-.323-3.416.015-.992.336-1.49.91-1.642 1.476-.152.566-.007 1.313.684 2.1.528.6 1.273 1.1 2.128 1.446h7.879a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1 0-1.5h3.813a5.976 5.976 0 0 1-.447-.456C5.18 7.479 4.798 6.231 5.11 5.066c.312-1.164 1.268-2.055 2.61-2.509 1.336-.451 2.877-.42 4.286-.043.856.23 1.684.592 2.409 1.074a.75.75 0 1 1-.83 1.25 6.723 6.723 0 0 0-1.968-.875Zm1.909 8.123a.75.75 0 0 1 1.015.309c.53.99.607 2.062.18 3.01-.421.94-1.289 1.648-2.441 2.038-1.336.452-2.877.42-4.286.043-1.409-.377-2.759-1.121-3.69-2.18a.75.75 0 1 1 1.127-.99c.696.791 1.765 1.403 2.952 1.721 1.186.318 2.418.323 3.416-.015.853-.288 1.34-.756 1.555-1.232.21-.467.205-1.049-.136-1.69a.75.75 0 0 1 .308-1.014Z" clip-rule="evenodd" /> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
2
resources/views/flux/editor/styles.blade.php
Normal file
2
resources/views/flux/editor/styles.blade.php
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
{!! app('flux')->editorStyles() !!}
|
||||
11
resources/views/flux/editor/subscript.blade.php
Normal file
11
resources/views/flux/editor/subscript.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Subscript') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="subscript">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 5 8 8"/><path d="m12 5-8 8"/><path d="M20 19h-4c0-1.5.44-2 1.5-2.5S20 15.33 20 14c0-.47-.17-.93-.48-1.29a2.11 2.11 0 0 0-2.62-.44c-.42.24-.74.62-.9 1.07"/></svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
11
resources/views/flux/editor/superscript.blade.php
Normal file
11
resources/views/flux/editor/superscript.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => null,
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Superscript') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="superscript">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m4 19 8-8"/><path d="m12 19-8-8"/><path d="M20 12h-4c0-1.5.442-2 1.5-2.5S20 8.334 20 7.002c0-.472-.17-.93-.484-1.29a2.105 2.105 0 0 0-2.617-.436c-.42.239-.738.614-.899 1.06"/></svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
50
resources/views/flux/editor/toolbar.blade.php
Normal file
50
resources/views/flux/editor/toolbar.blade.php
Normal file
@@ -0,0 +1,50 @@
|
||||
@aware(['variant' => null])
|
||||
|
||||
@props([
|
||||
'items' => null,
|
||||
'variant' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('block overflow-x-auto w-full')
|
||||
->add(match($variant) {
|
||||
'borderless' => 'rounded-lg bg-zinc-100 dark:bg-white/10 *:p-1.5 *:h-auto',
|
||||
default => [
|
||||
'bg-zinc-50 dark:bg-white/[6%] dark:border-white/5',
|
||||
'rounded-t-[calc(0.5rem-1px)]',
|
||||
'border-b border-zinc-200 dark:border-white/10',
|
||||
]
|
||||
})
|
||||
;
|
||||
@endphp
|
||||
|
||||
<ui-toolbar {{ $attributes->class($classes) }} wire:ignore aria-label="{{ __('Formatting') }}">
|
||||
<div class="h-10 p-2 flex gap-2 items-center">
|
||||
<?php if ($slot->isNotEmpty()): ?>
|
||||
{{ $slot }}
|
||||
<?php else: ?>
|
||||
<?php if ($items !== null): ?>
|
||||
<?php foreach (str($items)->explode(' ') as $item): ?>
|
||||
<?php if ($item === '|') $item = 'separator'; ?>
|
||||
<?php if ($item === '~') $item = 'spacer'; ?>
|
||||
<flux:delegate-component :component="'editor.' . $item"></flux:delegate-component>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<flux:editor.heading />
|
||||
<flux:editor.separator />
|
||||
<flux:editor.bold />
|
||||
<flux:editor.italic />
|
||||
<flux:editor.strike />
|
||||
<flux:editor.separator />
|
||||
<flux:editor.bullet />
|
||||
<flux:editor.ordered />
|
||||
<flux:editor.blockquote />
|
||||
<flux:editor.separator />
|
||||
<flux:editor.link />
|
||||
<flux:editor.separator />
|
||||
<flux:editor.align />
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</ui-toolbar>
|
||||
11
resources/views/flux/editor/underline.blade.php
Normal file
11
resources/views/flux/editor/underline.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘U',
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Underline') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="underline">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-5" aria-hidden="true"> <path fill-rule="evenodd" d="M4.75 2a.75.75 0 0 1 .75.75V9a4.5 4.5 0 1 0 9 0V2.75a.75.75 0 0 1 1.5 0V9A6 6 0 0 1 4 9V2.75A.75.75 0 0 1 4.75 2ZM2 17.25a.75.75 0 0 1 .75-.75h14.5a.75.75 0 0 1 0 1.5H2.75a.75.75 0 0 1-.75-.75Z" clip-rule="evenodd" /> </svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
11
resources/views/flux/editor/undo.blade.php
Normal file
11
resources/views/flux/editor/undo.blade.php
Normal file
@@ -0,0 +1,11 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'kbd' => '⌘Z',
|
||||
])
|
||||
|
||||
<flux:tooltip content="{{ __('Undo') }}" :$kbd class="contents">
|
||||
<flux:editor.button data-editor="undo">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/></svg>
|
||||
</flux:editor.button>
|
||||
</flux:tooltip>
|
||||
29
resources/views/flux/error.blade.php
Normal file
29
resources/views/flux/error.blade.php
Normal file
@@ -0,0 +1,29 @@
|
||||
@props([
|
||||
'icon' => 'exclamation-triangle',
|
||||
'bag' => 'default',
|
||||
'message' => null,
|
||||
'nested' => true,
|
||||
'name' => null,
|
||||
])
|
||||
|
||||
@php
|
||||
$errorBag = $errors->getBag($bag);
|
||||
$message ??= $name ? $errorBag->first($name) : null;
|
||||
|
||||
if ($name && (is_null($message) || $message === '') && filter_var($nested, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== false) {
|
||||
$message = $errorBag->first($name . '.*');
|
||||
}
|
||||
|
||||
$classes = Flux::classes('mt-3 text-sm font-medium text-red-500 dark:text-red-400')
|
||||
->add($message ? '' : 'hidden');
|
||||
@endphp
|
||||
|
||||
<div role="alert" aria-live="polite" aria-atomic="true" {{ $attributes->class($classes) }} data-flux-error>
|
||||
<?php if ($message) : ?>
|
||||
<?php if ($icon) : ?>
|
||||
<flux:icon :name="$icon" variant="mini" class="inline" />
|
||||
<?php endif; ?>
|
||||
|
||||
{{ $message }}
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
42
resources/views/flux/field.blade.php
Normal file
42
resources/views/flux/field.blade.php
Normal file
@@ -0,0 +1,42 @@
|
||||
@blaze
|
||||
|
||||
@props([
|
||||
'variant' => 'block',
|
||||
])
|
||||
|
||||
@php
|
||||
$classes = Flux::classes()
|
||||
->add('min-w-0') // This is here to allow nested input elements like flux::input.file to truncate properly...
|
||||
->add('[&:not(:has([data-flux-field])):has([data-flux-control][disabled])>[data-flux-label]]:opacity-50') // Dim labels for fields with no nested fields when a control is disabled...
|
||||
->add('[&:has(>[data-flux-radio-group][disabled])>[data-flux-label]]:opacity-50') // Special case for radio groups because they are nested fields...
|
||||
->add('[&:has(>[data-flux-checkbox-group][disabled])>[data-flux-label]]:opacity-50') // Special case for checkbox groups because they are nested fields...
|
||||
->add(match ($variant) {
|
||||
default => 'block',
|
||||
'inline' => [
|
||||
'grid gap-x-3 gap-y-1.5',
|
||||
'has-[[data-flux-label]~[data-flux-control]]:grid-cols-[1fr_auto]',
|
||||
'has-[[data-flux-control]~[data-flux-label]]:grid-cols-[auto_1fr]',
|
||||
'[&>[data-flux-control]~[data-flux-description]]:row-start-2 [&>[data-flux-control]~[data-flux-description]]:col-start-2',
|
||||
'[&>[data-flux-control]~[data-flux-error]]:col-span-2 [&>[data-flux-control]~[data-flux-error]]:mt-1', // Position error messages...
|
||||
'[&>[data-flux-label]~[data-flux-control]]:row-start-1 [&>[data-flux-label]~[data-flux-control]]:col-start-2',
|
||||
],
|
||||
})
|
||||
->add(match ($variant) {
|
||||
default => [ // Adjust spacing around label...
|
||||
'*:data-flux-label:mb-3 [&>[data-flux-label]:has(+[data-flux-description])]:mb-2',
|
||||
],
|
||||
'inline' => '',
|
||||
})
|
||||
->add(match ($variant) {
|
||||
default => [ // Adjust spacing around description...
|
||||
'[&>[data-flux-label]+[data-flux-description]]:mt-0',
|
||||
'[&>[data-flux-label]+[data-flux-description]]:mb-3',
|
||||
'[&>*:not([data-flux-label])+[data-flux-description]]:mt-3',
|
||||
],
|
||||
'inline' => '',
|
||||
});
|
||||
@endphp
|
||||
|
||||
<ui-field {{ $attributes->class($classes) }} data-flux-field>
|
||||
{{ $slot }}
|
||||
</ui-field>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user