[增添]添加了datasource的setting数据库以及默认值

This commit is contained in:
makotocc0107
2024-08-27 09:57:44 +08:00
parent d111dfaea4
commit 72eb990970
10955 changed files with 978898 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
@php
$isDisabled = $isDisabled();
$state = (bool) $getState();
@endphp
<div
x-data="{
error: undefined,
isLoading: false,
name: @js($getName()),
recordKey: @js($recordKey),
state: @js($state),
}"
x-init="
() => {
Livewire.hook('commit', ({ component, commit, succeed, fail, respond }) => {
succeed(({ snapshot, effect }) => {
$nextTick(() => {
if (component.id !== @js($this->getId())) {
return
}
if (! $refs.newState) {
return
}
const newState = $refs.newState.value === '1' ? true : false
if (state === newState) {
return
}
state = newState
})
})
})
}
"
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-checkbox flex items-center',
'px-3 py-4' => ! $isInline(),
])
}}
>
<input type="hidden" value="{{ $state ? 1 : 0 }}" x-ref="newState" />
<x-filament::input.checkbox
alpine-valid="! error"
:disabled="$isDisabled"
:x-bind:disabled="$isDisabled ? null : 'isLoading'"
x-model="state"
x-on:change="
isLoading = true
const response = await $wire.updateTableColumnState(
name,
recordKey,
$event.target.checked,
)
error = response?.error ?? undefined
isLoading = false
"
x-tooltip="
error === undefined
? false
: {
content: error,
theme: $store.theme,
}
"
x-on:click.stop=""
:attributes="
\Filament\Support\prepare_inherited_attributes($attributes)
->merge($getExtraInputAttributes(), escape: false)
"
/>
</div>

View File

@@ -0,0 +1,57 @@
@php
$canWrap = $canWrap();
$arrayState = $getState();
if ($arrayState instanceof \Illuminate\Support\Collection) {
$arrayState = $arrayState->all();
}
$arrayState = \Illuminate\Support\Arr::wrap($arrayState);
@endphp
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-color flex gap-1.5',
'flex-wrap' => $canWrap,
'px-3 py-4' => ! $isInline(),
])
}}
>
@if (count($arrayState))
@foreach ($arrayState as $state)
@php
$itemIsCopyable = $isCopyable($state);
$copyableState = $getCopyableState($state) ?? $state;
$copyMessage = $getCopyMessage($state);
$copyMessageDuration = $getCopyMessageDuration($state);
@endphp
<div
@if ($itemIsCopyable)
x-on:click="
window.navigator.clipboard.writeText(@js($copyableState))
$tooltip(@js($copyMessage), {
theme: $store.theme,
timeout: @js($copyMessageDuration),
})
"
@endif
@class([
'fi-ta-color-item h-6 w-6 rounded-md',
'cursor-pointer' => $itemIsCopyable,
])
@style([
"background-color: {$state}" => $state,
])
></div>
@endforeach
@elseif (($placeholder = $getPlaceholder()) !== null)
<x-filament-tables::columns.placeholder>
{{ $placeholder }}
</x-filament-tables::columns.placeholder>
@endif
</div>

View File

@@ -0,0 +1,67 @@
@php
use Filament\Tables\Columns\IconColumn\IconColumnSize;
$arrayState = $getState();
if ($arrayState instanceof \Illuminate\Support\Collection) {
$arrayState = $arrayState->all();
}
$arrayState = \Illuminate\Support\Arr::wrap($arrayState);
@endphp
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-icon flex gap-1.5',
'flex-wrap' => $canWrap(),
'px-3 py-4' => ! $isInline(),
'flex-col' => $isListWithLineBreaks(),
])
}}
>
@if (count($arrayState))
@foreach ($arrayState as $state)
@if ($icon = $getIcon($state))
@php
$color = $getColor($state) ?? 'gray';
$size = $getSize($state) ?? IconColumnSize::Large;
@endphp
<x-filament::icon
:icon="$icon"
@class([
'fi-ta-icon-item',
match ($size) {
IconColumnSize::ExtraSmall, 'xs' => 'fi-ta-icon-item-size-xs h-3 w-3',
IconColumnSize::Small, 'sm' => 'fi-ta-icon-item-size-sm h-4 w-4',
IconColumnSize::Medium, 'md' => 'fi-ta-icon-item-size-md h-5 w-5',
IconColumnSize::Large, 'lg' => 'fi-ta-icon-item-size-lg h-6 w-6',
IconColumnSize::ExtraLarge, 'xl' => 'fi-ta-icon-item-size-xl h-7 w-7',
IconColumnSize::TwoExtraLarge, IconColumnSize::ExtraExtraLarge, '2xl' => 'fi-ta-icon-item-size-2xl h-8 w-8',
default => $size,
},
match ($color) {
'gray' => 'text-gray-400 dark:text-gray-500',
default => 'fi-color-custom text-custom-500 dark:text-custom-400',
},
is_string($color) ? 'fi-color-' . $color : null,
])
@style([
\Filament\Support\get_color_css_variables(
$color,
shades: [400, 500],
alias: 'tables::columns.icon-column.item',
) => $color !== 'gray',
])
/>
@endif
@endforeach
@elseif (($placeholder = $getPlaceholder()) !== null)
<x-filament-tables::columns.placeholder>
{{ $placeholder }}
</x-filament-tables::columns.placeholder>
@endif
</div>

View File

@@ -0,0 +1,143 @@
@php
$state = $getState();
if ($state instanceof \Illuminate\Support\Collection) {
$state = $state->all();
}
$state = \Illuminate\Support\Arr::wrap($state);
$limit = $getLimit();
$limitedState = array_slice($state, 0, $limit);
$isCircular = $isCircular();
$isSquare = $isSquare();
$isStacked = $isStacked();
$overlap = $isStacked ? ($getOverlap() ?? 2) : null;
$ring = $isStacked ? ($getRing() ?? 2) : null;
$height = $getHeight() ?? ($isStacked ? '2rem' : '2.5rem');
$width = $getWidth() ?? (($isCircular || $isSquare) ? $height : null);
$stateCount = count($state);
$limitedStateCount = count($limitedState);
$defaultImageUrl = $getDefaultImageUrl();
if ((! $limitedStateCount) && filled($defaultImageUrl)) {
$limitedState = [null];
$limitedStateCount = 1;
}
$ringClasses = \Illuminate\Support\Arr::toCssClasses([
'ring-white dark:ring-gray-900',
match ($ring) {
0 => null,
1 => 'ring-1',
2 => 'ring-2',
3 => 'ring',
4 => 'ring-4',
default => $ring,
},
]);
$hasLimitedRemainingText = $hasLimitedRemainingText() && ($limitedStateCount < $stateCount);
$isLimitedRemainingTextSeparate = $isLimitedRemainingTextSeparate();
$limitedRemainingTextSizeClasses = match ($getLimitedRemainingTextSize()) {
'xs' => 'text-xs',
'sm', null => 'text-sm',
'base', 'md' => 'text-base',
'lg' => 'text-lg',
default => $size,
};
@endphp
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-image',
'px-3 py-4' => ! $isInline(),
])
}}
>
@if ($limitedStateCount)
<div class="flex items-center gap-x-2.5">
<div
@class([
'flex',
'flex-wrap' => $canWrap(),
match ($overlap) {
0 => null,
1 => '-space-x-1',
2 => '-space-x-2',
3 => '-space-x-3',
4 => '-space-x-4',
5 => '-space-x-5',
6 => '-space-x-6',
7 => '-space-x-7',
8 => '-space-x-8',
default => 'gap-1.5',
},
])
>
@foreach ($limitedState as $stateItem)
<img
src="{{ filled($stateItem) ? $getImageUrl($stateItem) : $defaultImageUrl }}"
{{
$getExtraImgAttributeBag()
->class([
'max-w-none object-cover object-center',
'rounded-full' => $isCircular,
$ringClasses,
])
->style([
"height: {$height}" => $height,
"width: {$width}" => $width,
])
}}
/>
@endforeach
@if ($hasLimitedRemainingText && (! $isLimitedRemainingTextSeparate) && $isCircular)
<div
style="
@if ($height) height: {{ $height }}; @endif
@if ($width) width: {{ $width }}; @endif
"
@class([
'flex items-center justify-center bg-gray-100 font-medium text-gray-500 dark:bg-gray-800 dark:text-gray-400',
'rounded-full' => $isCircular,
$limitedRemainingTextSizeClasses,
$ringClasses,
])
@style([
"height: {$height}" => $height,
"width: {$width}" => $width,
])
>
<span class="-ms-0.5">
+{{ $stateCount - $limitedStateCount }}
</span>
</div>
@endif
</div>
@if ($hasLimitedRemainingText && ($isLimitedRemainingTextSeparate || (! $isCircular)))
<div
@class([
'font-medium text-gray-500 dark:text-gray-400',
$limitedRemainingTextSizeClasses,
])
>
+{{ $stateCount - $limitedStateCount }}
</div>
@endif
</div>
@elseif (($placeholder = $getPlaceholder()) !== null)
<x-filament-tables::columns.placeholder>
{{ $placeholder }}
</x-filament-tables::columns.placeholder>
@endif
</div>

View File

@@ -0,0 +1,29 @@
@php
$columns = $getGridColumns();
@endphp
<div {{ $attributes->merge($getExtraAttributes(), escape: false) }}>
<x-filament::grid
:default="$columns['default'] ?? 1"
:sm="$columns['sm'] ?? null"
:md="$columns['md'] ?? null"
:lg="$columns['lg'] ?? null"
:xl="$columns['xl'] ?? null"
:two-xl="$columns['2xl'] ?? null"
@class([
(($columns['default'] ?? 1) === 1) ? 'gap-1' : 'gap-3',
($columns['sm'] ?? null) ? (($columns['sm'] === 1) ? 'sm:gap-1' : 'sm:gap-3') : null,
($columns['md'] ?? null) ? (($columns['md'] === 1) ? 'md:gap-1' : 'md:gap-3') : null,
($columns['lg'] ?? null) ? (($columns['lg'] === 1) ? 'lg:gap-1' : 'lg:gap-3') : null,
($columns['xl'] ?? null) ? (($columns['xl'] === 1) ? 'xl:gap-1' : 'xl:gap-3') : null,
($columns['2xl'] ?? null) ? (($columns['2xl'] === 1) ? '2xl:gap-1' : '2xl:gap-3') : null,
])
>
<x-filament-tables::columns.layout
:components="$getComponents()"
grid
:record="$getRecord()"
:record-key="$recordKey"
/>
</x-filament::grid>
</div>

View File

@@ -0,0 +1,13 @@
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class(['fi-ta-panel rounded-lg bg-gray-50 p-4 ring-1 ring-inset ring-gray-950/5 dark:bg-white/5 dark:ring-white/10'])
}}
>
<x-filament-tables::columns.layout
:components="$getComponents()"
:record="$getRecord()"
:record-key="$recordKey"
/>
</div>

View File

@@ -0,0 +1,24 @@
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-split flex',
match ($getFromBreakpoint()) {
'sm' => 'flex-col gap-2 sm:flex-row sm:items-center sm:gap-3',
'md' => 'flex-col gap-2 md:flex-row md:items-center md:gap-3',
'lg' => 'flex-col gap-2 lg:flex-row lg:items-center lg:gap-3',
'xl' => 'flex-col gap-2 xl:flex-row xl:items-center xl:gap-3',
'2xl' => 'flex-col gap-2 2xl:flex-row 2xl:items-center 2xl:gap-3',
default => 'items-center gap-3',
},
])
}}
>
<x-filament-tables::columns.layout
:components="$getComponents()"
:record="$getRecord()"
:record-key="$recordKey"
:row-loop="$getRowLoop()"
/>
</div>

View File

@@ -0,0 +1,39 @@
@php
use Filament\Support\Enums\Alignment;
$alignment = $getAlignment() ?? Alignment::Start;
if (! $alignment instanceof Alignment) {
$alignment = filled($alignment) ? (Alignment::tryFrom($alignment) ?? $alignment) : null;
}
@endphp
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'flex flex-col',
match ($alignment) {
Alignment::Start, Alignment::Left => 'items-start',
Alignment::Center => 'items-center',
Alignment::End, Alignment::Right => 'items-end',
Alignment::Justify, Alignment::Between => null,
default => $alignment,
},
match ($space = $getSpace()) {
1 => 'space-y-1',
2 => 'space-y-2',
3 => 'space-y-3',
default => $space,
},
])
}}
>
<x-filament-tables::columns.layout
:components="$getComponents()"
:record="$getRecord()"
:record-key="$recordKey"
:row-loop="$getRowLoop()"
/>
</div>

View File

@@ -0,0 +1,114 @@
@php
$canSelectPlaceholder = $canSelectPlaceholder();
$isDisabled = $isDisabled();
$state = $getState();
if ($state instanceof \BackedEnum) {
$state = $state->value;
}
$state = strval($state);
@endphp
<div
x-data="{
error: undefined,
isLoading: false,
name: @js($getName()),
recordKey: @js($recordKey),
state: @js($state),
}"
x-init="
() => {
Livewire.hook('commit', ({ component, commit, succeed, fail, respond }) => {
succeed(({ snapshot, effect }) => {
$nextTick(() => {
if (component.id !== @js($this->getId())) {
return
}
if (! $refs.newState) {
return
}
let newState = $refs.newState.value
if (state === newState) {
return
}
state = newState
})
})
})
}
"
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-select',
'px-3 py-4' => ! $isInline(),
])
}}
>
<input
type="hidden"
value="{{ str($state)->replace('"', '\\"') }}"
x-ref="newState"
/>
<x-filament::input.wrapper
:alpine-disabled="'isLoading || ' . \Illuminate\Support\Js::from($isDisabled)"
alpine-valid="error === undefined"
x-tooltip="
error === undefined
? false
: {
content: error,
theme: $store.theme,
}
"
x-on:click.stop=""
>
<x-filament::input.select
:disabled="$isDisabled"
:x-bind:disabled="$isDisabled ? null : 'isLoading'"
x-model="state"
x-on:change="
isLoading = true
const response = await $wire.updateTableColumnState(
name,
recordKey,
$event.target.value,
)
error = response?.error ?? undefined
if (! error) {
state = response
}
isLoading = false
"
:attributes="\Filament\Support\prepare_inherited_attributes($getExtraInputAttributeBag())"
>
@if ($canSelectPlaceholder)
<option value="">{{ $getPlaceholder() }}</option>
@endif
@foreach ($getOptions() as $value => $label)
<option
@disabled($isOptionDisabled($value, $label))
value="{{ $value }}"
>
{{ $label }}
</option>
@endforeach
</x-filament::input.select>
</x-filament::input.wrapper>
</div>

View File

@@ -0,0 +1,54 @@
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class(['fi-ta-icon-count-summary grid gap-y-1.5 px-3 py-4'])
}}
>
@if (filled($label = $getLabel()))
<p class="text-sm font-medium text-gray-950 dark:text-white">
{{ $label }}
</p>
@endif
@if ($state = $getState())
<div class="grid gap-y-1.5">
@foreach ($state as $color => $icons)
@php
$color = json_decode($color);
@endphp
@foreach ($icons as $icon => $count)
@if (filled($icon))
<div class="flex items-center justify-end gap-x-1.5">
<span
class="text-sm text-gray-500 dark:text-gray-400"
>
{{ $count }}
</span>
<x-filament::icon
:icon="$icon"
@class([
'fi-ta-icon-count-summary-icon h-6 w-6',
match ($color) {
'gray' => 'text-gray-400 dark:text-gray-500',
default => 'fi-color-custom text-custom-500 dark:text-custom-400',
},
is_string($color) ? 'fi-color-' . $color : null,
])
@style([
\Filament\Support\get_color_css_variables(
$color,
shades: [400, 500],
alias: 'tables::columns.summaries.icon-count.icon',
) => $color !== 'gray',
])
/>
</div>
@endif
@endforeach
@endforeach
</div>
@endif
</div>

View File

@@ -0,0 +1,31 @@
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class(['fi-ta-range-summary grid gap-y-1 px-3 py-4'])
}}
>
@php
$state = $formatState($getState());
$from = $state[0] ?? null;
$to = $state[1] ?? null;
@endphp
@if (filled($label = $getLabel()))
<span class="text-sm font-medium text-gray-950 dark:text-white">
{{ $label }}
</span>
@endif
@if (filled($from) || filled($to))
<span class="text-sm text-gray-500 dark:text-gray-400">
{{ $from }}
@if (filled($from) && filled($to))
-
@endif
{{ $to }}
</span>
@endif
</div>

View File

@@ -0,0 +1,17 @@
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class(['fi-ta-text-summary grid gap-y-1 px-3 py-4'])
}}
>
@if (filled($label = $getLabel()))
<span class="text-sm font-medium text-gray-950 dark:text-white">
{{ $label }}
</span>
@endif
<span class="text-sm text-gray-500 dark:text-gray-400">
{{ $formatState($getState()) }}
</span>
</div>

View File

@@ -0,0 +1,27 @@
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class(['fi-ta-values-summary grid gap-y-1 px-3 py-4'])
}}
>
@if (filled($label = $getLabel()))
<span class="text-sm font-medium text-gray-950 dark:text-white">
{{ $label }}
</span>
@endif
@if ($state = $getState())
<ul
@class([
'list-inside list-disc' => $isBulleted(),
])
>
@foreach ($state as $stateItem)
<li class="text-sm text-gray-500 dark:text-gray-400">
{{ $formatState($stateItem) }}
</li>
@endforeach
</ul>
@endif
</div>

View File

@@ -0,0 +1,314 @@
@php
use Filament\Support\Enums\Alignment;
use Filament\Support\Enums\FontFamily;
use Filament\Support\Enums\FontWeight;
use Filament\Support\Enums\IconPosition;
use Filament\Tables\Columns\TextColumn\TextColumnSize;
$alignment = $getAlignment();
$canWrap = $canWrap();
$descriptionAbove = $getDescriptionAbove();
$descriptionBelow = $getDescriptionBelow();
$iconPosition = $getIconPosition();
$isBadge = $isBadge();
$isBulleted = $isBulleted();
$isListWithLineBreaks = $isListWithLineBreaks();
$isLimitedListExpandable = $isLimitedListExpandable();
$url = $getUrl();
if (! $alignment instanceof Alignment) {
$alignment = filled($alignment) ? (Alignment::tryFrom($alignment) ?? $alignment) : null;
}
$arrayState = $getState();
if ($arrayState instanceof \Illuminate\Support\Collection) {
$arrayState = $arrayState->all();
}
$listLimit = 1;
if (is_array($arrayState)) {
if ($listLimit = $getListLimit()) {
$limitedArrayStateCount = (count($arrayState) > $listLimit) ? (count($arrayState) - $listLimit) : 0;
if (! $isListWithLineBreaks) {
$arrayState = array_slice($arrayState, 0, $listLimit);
}
}
$listLimit ??= count($arrayState);
if ((! $isListWithLineBreaks) && (! $isBadge)) {
$arrayState = implode(
', ',
array_map(
fn ($value) => $value instanceof \Filament\Support\Contracts\HasLabel ? $value->getLabel() : $value,
$arrayState,
),
);
}
}
$arrayState = \Illuminate\Support\Arr::wrap($arrayState);
@endphp
<div
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-text grid w-full gap-y-1',
'px-3 py-4' => ! $isInline(),
])
}}
>
@if (count($arrayState))
@if (filled($descriptionAbove))
<p
@class([
'text-sm text-gray-500 dark:text-gray-400',
'whitespace-normal' => $canWrap,
])
>
{{ $descriptionAbove }}
</p>
@endif
<{{ $isListWithLineBreaks ? 'ul' : 'div' }}
@class([
'flex' => ! $isBulleted,
'flex-col' => (! $isBulleted) && $isListWithLineBreaks,
'list-inside list-disc' => $isBulleted,
'gap-1.5' => $isBadge,
'flex-wrap' => $isBadge && (! $isListWithLineBreaks),
match ($alignment) {
Alignment::Start => 'text-start',
Alignment::Center => 'text-center',
Alignment::End => 'text-end',
Alignment::Left => 'text-left',
Alignment::Right => 'text-right',
Alignment::Justify, Alignment::Between => 'text-justify',
default => $alignment,
},
match ($alignment) {
Alignment::Start, Alignment::Left => 'justify-start',
Alignment::Center => 'justify-center',
Alignment::End, Alignment::Right => 'justify-end',
Alignment::Between, Alignment::Justify => 'justify-between',
default => null,
} => $isBulleted || (! $isListWithLineBreaks),
match ($alignment) {
Alignment::Start, Alignment::Left => 'items-start',
Alignment::Center => 'items-center',
Alignment::End, Alignment::Right => 'items-end',
Alignment::Between, Alignment::Justify => 'items-stretch',
default => null,
} => $isListWithLineBreaks && (! $isBulleted),
])
@if ($isListWithLineBreaks && $isLimitedListExpandable)
x-data="{ isLimited: true }"
@endif
>
@foreach ($arrayState as $state)
@if (filled($formattedState = $formatState($state)) &&
(! ($isListWithLineBreaks && (! $isLimitedListExpandable) && ($loop->iteration > $listLimit))))
@php
$color = $getColor($state);
$copyableState = $getCopyableState($state) ?? $state;
$copyMessage = $getCopyMessage($state);
$copyMessageDuration = $getCopyMessageDuration($state);
$fontFamily = $getFontFamily($state);
$icon = $getIcon($state);
$iconColor = $getIconColor($state) ?? $color;
$itemIsCopyable = $isCopyable($state);
$lineClamp = $getLineClamp($state);
$size = $getSize($state);
$weight = $getWeight($state);
$iconClasses = \Illuminate\Support\Arr::toCssClasses([
'fi-ta-text-item-icon h-5 w-5',
match ($iconColor) {
'gray', null => 'text-gray-400 dark:text-gray-500',
default => 'text-custom-500',
},
]);
$iconStyles = \Illuminate\Support\Arr::toCssStyles([
\Filament\Support\get_color_css_variables(
$iconColor,
shades: [500],
alias: 'tables::columns.text-column.item.icon',
) => $iconColor !== 'gray',
]);
@endphp
<{{ $isListWithLineBreaks ? 'li' : 'div' }}
@if ($itemIsCopyable)
x-on:click="
window.navigator.clipboard.writeText(@js($copyableState))
$tooltip(@js($copyMessage), {
theme: $store.theme,
timeout: @js($copyMessageDuration),
})
"
@endif
@if ($isListWithLineBreaks && ($loop->iteration > $listLimit))
x-cloak
x-show="! isLimited"
x-transition
@endif
@class([
'flex' => ! $isBulleted,
'max-w-max' => ! ($isBulleted || $isBadge),
'w-max' => $isBadge,
'cursor-pointer' => $itemIsCopyable,
match ($color) {
null => 'text-gray-950 dark:text-white',
'gray' => 'text-gray-500 dark:text-gray-400',
default => 'text-custom-600 dark:text-custom-400',
} => $isBulleted,
])
@style([
\Filament\Support\get_color_css_variables(
$color,
shades: [400, 600],
alias: 'tables::columns.text-column.item.container',
) => $isBulleted && (! in_array($color, [null, 'gray'])),
])
>
@if ($isBadge)
<x-filament::badge
:color="$color"
:icon="$icon"
:icon-position="$iconPosition"
>
{{ $formattedState }}
</x-filament::badge>
@else
<div
@class([
'fi-ta-text-item inline-flex items-center gap-1.5',
'group/item' => $url,
match ($color) {
null, 'gray' => null,
default => 'fi-color-custom',
},
is_string($color) ? "fi-color-{$color}" : null,
])
>
@if ($icon && in_array($iconPosition, [IconPosition::Before, 'before']))
<x-filament::icon
:icon="$icon"
:class="$iconClasses"
:style="$iconStyles"
/>
@endif
<span
@class([
'fi-ta-text-item-label',
'group-hover/item:underline group-focus-visible/item:underline' => $url,
'whitespace-normal' => $canWrap,
'line-clamp-[--line-clamp]' => $lineClamp,
match ($size) {
TextColumnSize::ExtraSmall, 'xs' => 'text-xs',
TextColumnSize::Small, 'sm', null => 'text-sm leading-6',
TextColumnSize::Medium, 'base', 'md' => 'text-base',
TextColumnSize::Large, 'lg' => 'text-lg',
default => $size,
},
match ($color) {
null => 'text-gray-950 dark:text-white',
'gray' => 'text-gray-500 dark:text-gray-400',
default => 'text-custom-600 dark:text-custom-400',
},
match ($weight) {
FontWeight::Thin, 'thin' => 'font-thin',
FontWeight::ExtraLight, 'extralight' => 'font-extralight',
FontWeight::Light, 'light' => 'font-light',
FontWeight::Medium, 'medium' => 'font-medium',
FontWeight::SemiBold, 'semibold' => 'font-semibold',
FontWeight::Bold, 'bold' => 'font-bold',
FontWeight::ExtraBold, 'extrabold' => 'font-extrabold',
FontWeight::Black, 'black' => 'font-black',
default => $weight,
},
match ($fontFamily) {
FontFamily::Sans, 'sans' => 'font-sans',
FontFamily::Serif, 'serif' => 'font-serif',
FontFamily::Mono, 'mono' => 'font-mono',
default => $fontFamily,
},
])
@style([
\Filament\Support\get_color_css_variables(
$color,
shades: [400, 600],
alias: 'tables::columns.text-column.item.label',
) => ! in_array($color, [null, 'gray']),
"--line-clamp: {$lineClamp}" => $lineClamp,
])
>
{{ $formattedState }}
</span>
@if ($icon && in_array($iconPosition, [IconPosition::After, 'after']))
<x-filament::icon
:icon="$icon"
:class="$iconClasses"
:style="$iconStyles"
/>
@endif
</div>
@endif
</{{ $isListWithLineBreaks ? 'li' : 'div' }}>
@endif
@endforeach
@if ($limitedArrayStateCount ?? 0)
<{{ $isListWithLineBreaks ? 'li' : 'div' }}>
@if ($isLimitedListExpandable)
<x-filament::link
color="gray"
tag="button"
x-on:click.prevent="isLimited = false"
x-show="isLimited"
>
{{ trans_choice('filament-tables::table.columns.text.actions.expand_list', $limitedArrayStateCount) }}
</x-filament::link>
<x-filament::link
color="gray"
tag="button"
x-cloak
x-on:click.prevent="isLimited = true"
x-show="! isLimited"
>
{{ trans_choice('filament-tables::table.columns.text.actions.collapse_list', $limitedArrayStateCount) }}
</x-filament::link>
@else
<span class="text-sm text-gray-500 dark:text-gray-400">
{{ trans_choice('filament-tables::table.columns.text.more_list_items', $limitedArrayStateCount) }}
</span>
@endif
</{{ $isListWithLineBreaks ? 'li' : 'div' }}>
@endif
</{{ $isListWithLineBreaks ? 'ul' : 'div' }}>
@if (filled($descriptionBelow))
<p
@class([
'text-sm text-gray-500 dark:text-gray-400',
'whitespace-normal' => $canWrap,
])
>
{{ $descriptionBelow }}
</p>
@endif
@elseif (($placeholder = $getPlaceholder()) !== null)
<x-filament-tables::columns.placeholder>
{{ $placeholder }}
</x-filament-tables::columns.placeholder>
@endif
</div>

View File

@@ -0,0 +1,142 @@
@php
use Filament\Support\Enums\Alignment;
$isDisabled = $isDisabled();
$state = $getState();
$mask = $getMask();
$alignment = $getAlignment() ?? Alignment::Start;
if (! $alignment instanceof Alignment) {
$alignment = filled($alignment) ? (Alignment::tryFrom($alignment) ?? $alignment) : null;
}
if (filled($mask)) {
$type = 'text';
} else {
$type = $getType();
}
@endphp
<div
x-data="{
error: undefined,
isEditing: false,
isLoading: false,
name: @js($getName()),
recordKey: @js($recordKey),
state: @js($state),
}"
x-init="
() => {
Livewire.hook('commit', ({ component, commit, succeed, fail, respond }) => {
succeed(({ snapshot, effect }) => {
$nextTick(() => {
if (component.id !== @js($this->getId())) {
return
}
if (isEditing) {
return
}
if (! $refs.newState) {
return
}
let newState = $refs.newState.value
if (state === newState) {
return
}
state = newState
})
})
})
}
"
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-text-input',
'px-3 py-4' => ! $isInline(),
])
}}
>
<input
type="hidden"
value="{{ str($state)->replace('"', '\\"') }}"
x-ref="newState"
/>
<x-filament::input.wrapper
:alpine-disabled="'isLoading || ' . \Illuminate\Support\Js::from($isDisabled)"
alpine-valid="error === undefined"
x-tooltip="
error === undefined
? false
: {
content: error,
theme: $store.theme,
}
"
x-on:click.stop=""
>
{{-- format-ignore-start --}}
<x-filament::input
:disabled="$isDisabled"
:input-mode="$getInputMode()"
:placeholder="$getPlaceholder()"
:step="$getStep()"
:type="$type"
:x-bind:disabled="$isDisabled ? null : 'isLoading'"
x-model="state"
x-on:blur="isEditing = false"
x-on:focus="isEditing = true"
:attributes="
\Filament\Support\prepare_inherited_attributes(
$getExtraInputAttributeBag()
->merge([
'x-on:change' . ($type === 'number' ? '.debounce.1s' : null) => '
isLoading = true
const response = await $wire.updateTableColumnState(
name,
recordKey,
$event.target.value,
)
error = response?.error ?? undefined
if (! error) {
state = response
}
isLoading = false
',
'x-mask' . ($mask instanceof \Filament\Support\RawJs ? ':dynamic' : '') => filled($mask) ? $mask : null,
])
->class([
match ($alignment) {
Alignment::Start => 'text-start',
Alignment::Center => 'text-center',
Alignment::End => 'text-end',
Alignment::Left => 'text-left',
Alignment::Right => 'text-right',
Alignment::Justify, Alignment::Between => 'text-justify',
default => $alignment,
},
])
)
"
/>
{{-- format-ignore-end --}}
</x-filament::input.wrapper>
</div>

View File

@@ -0,0 +1,174 @@
@php
$isDisabled = $isDisabled();
$state = $getState();
@endphp
<div
wire:key="{{ $this->getId() }}.table.record.{{ $recordKey }}.column.{{ $getName() }}.toggle-column.{{ $state ? 'true' : 'false' }}"
>
<div
x-data="{
error: undefined,
state: @js((bool) $state),
isLoading: false,
}"
wire:ignore
{{
$attributes
->merge($getExtraAttributes(), escape: false)
->class([
'fi-ta-toggle',
'px-3 py-4' => ! $isInline(),
])
}}
>
@php
$offColor = $getOffColor() ?? 'gray';
$onColor = $getOnColor() ?? 'primary';
@endphp
<div
role="switch"
aria-checked="false"
x-bind:aria-checked="state.toString()"
@if (! $isDisabled)
x-on:click.stop="
if (isLoading) {
return
}
const updatedState = ! state
// Only update the state if the toggle is being turned off,
// otherwise it will flicker on twice when Livewire replaces
// the element.
if (state) {
state = false
}
isLoading = true
const response = await $wire.updateTableColumnState(
@js($getName()),
@js($recordKey),
updatedState,
)
error = response?.error ?? undefined
// The state is only updated on the frontend if the toggle is
// being turned off, so we only need to reset it then.
if (! state && error) {
state = ! state
}
isLoading = false
"
x-tooltip="
error === undefined
? false
: {
content: error,
theme: $store.theme,
}
"
@endif
x-bind:class="
(state
? '{{
\Illuminate\Support\Arr::toCssClasses([
match ($onColor) {
'gray' => 'bg-gray-200 dark:bg-gray-700',
default => 'fi-color-custom bg-custom-600',
},
is_string($onColor) ? "fi-color-{$onColor}" : null,
])
}}'
: '{{
\Illuminate\Support\Arr::toCssClasses([
match ($offColor) {
'gray' => 'bg-gray-200 dark:bg-gray-700',
default => 'fi-color-custom bg-custom-600',
},
is_string($offColor) ? "fi-color-{$offColor}" : null,
])
}}') +
(isLoading ? ' opacity-70 pointer-events-none' : '')
"
x-bind:style="
state
? '{{
\Filament\Support\get_color_css_variables(
$onColor,
shades: [600],
alias: 'tables::columns.toggle-column.on',
)
}}'
: '{{
\Filament\Support\get_color_css_variables(
$offColor,
shades: [600],
alias: 'tables::columns.toggle-column.off',
)
}}'
"
@class([
'relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent outline-none transition-colors duration-200 ease-in-out',
'pointer-events-none opacity-70' => $isDisabled,
])
>
<span
class="pointer-events-none relative inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
x-bind:class="{
'translate-x-5 rtl:-translate-x-5': state,
'translate-x-0': ! state,
}"
>
<span
class="absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
aria-hidden="true"
x-bind:class="{
'opacity-0 ease-out duration-100': state,
'opacity-100 ease-in duration-200': ! state,
}"
>
@if ($hasOffIcon())
<x-filament::icon
:icon="$getOffIcon()"
@class([
'fi-ta-toggle-off-icon h-3 w-3',
match ($offColor) {
'gray' => 'text-gray-400 dark:text-gray-700',
default => 'text-custom-600',
},
])
/>
@endif
</span>
<span
class="absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
aria-hidden="true"
x-bind:class="{
'opacity-100 ease-in duration-200': state,
'opacity-0 ease-out duration-100': ! state,
}"
>
@if ($hasOnIcon())
<x-filament::icon
:icon="$getOnIcon()"
x-cloak="x-cloak"
@class([
'fi-ta-toggle-on-icon h-3 w-3',
match ($onColor) {
'gray' => 'text-gray-400 dark:text-gray-700',
default => 'text-custom-600',
},
])
/>
@endif
</span>
</span>
</div>
</div>
</div>