Skip to content

Commit b875154

Browse files
committed
copyable fields
1 parent a09fea5 commit b875154

File tree

6 files changed

+166
-9
lines changed

6 files changed

+166
-9
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{{ $text }}
2+
<button
3+
type="button"
4+
class="btn btn--light btn--sm btn--icon"
5+
aria-label="{{ __('Copy') }}"
6+
x-cloak
7+
x-bind:disabled="copied"
8+
x-data="{ copied: false }"
9+
x-on:click="(event) => {
10+
navigator.clipboard.writeText('{{ $value }}');
11+
copied = true;
12+
setTimeout(() => copied = false, 2500);
13+
}"
14+
>
15+
<x-root::icon x-show="! copied" name="clipboard" class="btn__icon" />
16+
<x-root::icon x-show="copied" name="check" class="btn__icon" />
17+
</button>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<svg
2+
aria-hidden="true"
3+
fill="none"
4+
focusable="false"
5+
height="24"
6+
stroke-linecap="round"
7+
stroke-linejoin="round"
8+
stroke-width="2.5"
9+
stroke="currentColor"
10+
viewBox="0 0 24 24"
11+
width="24"
12+
xmlns="http://www.w3.org/2000/svg"
13+
{{ $attributes }}
14+
>
15+
<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path>
16+
<rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>
17+
</svg>

src/Fields/Field.php

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Closure;
88
use Cone\Root\Filters\Filter;
99
use Cone\Root\Filters\RenderableFilter;
10+
use Cone\Root\Support\Copyable;
1011
use Cone\Root\Traits\Authorizable;
1112
use Cone\Root\Traits\HasAttributes;
1213
use Cone\Root\Traits\Makeable;
@@ -144,6 +145,11 @@ abstract class Field implements Arrayable, JsonSerializable
144145
*/
145146
protected bool|Closure $translatable = false;
146147

148+
/**
149+
* Indicates whether the field is copyable.
150+
*/
151+
protected bool|Closure $copyable = false;
152+
147153
/**
148154
* Create a new field instance.
149155
*/
@@ -360,6 +366,24 @@ public function resolveSearchQuery(Request $request, Builder $query, mixed $valu
360366
: $query;
361367
}
362368

369+
/**
370+
* Set the copyable attribute.
371+
*/
372+
public function copyable(bool|Closure $value = true): static
373+
{
374+
$this->copyable = $value;
375+
376+
return $this;
377+
}
378+
379+
/**
380+
* Determine whether the field value is copyable.
381+
*/
382+
public function isCopyable(): bool
383+
{
384+
return $this->copyable instanceof Closure ? call_user_func($this->copyable) : $this->copyable;
385+
}
386+
363387
/**
364388
* Set the translatable attribute.
365389
*/
@@ -520,15 +544,22 @@ public function resolveFormat(Request $request, Model $model): ?string
520544
{
521545
$value = $this->resolveValue($request, $model);
522546

523-
if (is_null($this->formatResolver)) {
524-
return match (true) {
525-
is_array($value) => json_encode($value),
526-
is_null($value) => $value,
527-
default => (string) $value,
528-
};
547+
$formattedValue = match (true) {
548+
! is_null($this->formatResolver) => call_user_func_array($this->formatResolver, [$request, $model, $value]),
549+
is_array($value) => json_encode($value),
550+
is_null($value) => $value,
551+
default => (string) $value,
552+
};
553+
554+
if (! $this->isCopyable()) {
555+
return $formattedValue;
529556
}
530557

531-
return call_user_func_array($this->formatResolver, [$request, $model, $value]);
558+
return (string) Copyable::make($formattedValue, match (true) {
559+
is_array($value) => json_encode($value),
560+
is_null($value) => $value,
561+
default => (string) $value,
562+
});
532563
}
533564

534565
/**

src/Support/Alert.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
namespace Cone\Root\Support;
66

77
use Illuminate\Contracts\Support\Arrayable;
8+
use Illuminate\Contracts\Support\Htmlable;
89
use Illuminate\Contracts\Support\Jsonable;
910
use Stringable;
1011

11-
class Alert implements Arrayable, Jsonable, Stringable
12+
class Alert implements Arrayable, Htmlable, Jsonable, Stringable
1213
{
1314
public const string INFO = 'info';
1415

@@ -90,11 +91,19 @@ public function toJson($options = 0): string
9091
return json_encode($this->toArray());
9192
}
9293

94+
/**
95+
* Get content as a string of HTML.
96+
*/
97+
public function toHtml(): string
98+
{
99+
return $this->message;
100+
}
101+
93102
/**
94103
* Get the string representation of the object.
95104
*/
96105
public function __toString(): string
97106
{
98-
return $this->message;
107+
return $this->toHtml();
99108
}
100109
}

src/Support/Copyable.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Cone\Root\Support;
6+
7+
use Illuminate\Contracts\Support\Htmlable;
8+
use Illuminate\Contracts\Support\Renderable;
9+
use Illuminate\Support\Facades\Blade;
10+
use Stringable;
11+
12+
class Copyable implements Htmlable, Renderable, Stringable
13+
{
14+
/**
15+
* Create a new copyable instance.
16+
*/
17+
public function __construct(protected string $text, protected string $value)
18+
{
19+
//
20+
}
21+
22+
/**
23+
* Make a new copyable instance.
24+
*/
25+
public static function make(string $text, ?string $value = null): static
26+
{
27+
return new static($text, $value ?: $text);
28+
}
29+
30+
/**
31+
* Get the evaluated contents of the object.
32+
*/
33+
public function render(): string
34+
{
35+
return Blade::render(sprintf('<x-root::copyable text="%s" value="%s" />', $this->text, $this->value));
36+
}
37+
38+
/**
39+
* Get content as a string of HTML.
40+
*/
41+
public function toHtml(): string
42+
{
43+
return $this->render();
44+
}
45+
46+
/**
47+
* Get the string representation of the object.
48+
*/
49+
public function __toString(): string
50+
{
51+
return $this->toHtml();
52+
}
53+
}

src/View/Components/Copyable.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Cone\Root\View\Components;
6+
7+
use Illuminate\View\Component;
8+
use Illuminate\View\View;
9+
10+
class Copyable extends Component
11+
{
12+
/**
13+
* Create a new component instance.
14+
*/
15+
public function __construct(protected string $text, protected string $value)
16+
{
17+
//
18+
}
19+
20+
/**
21+
* Get the view / view contents that represent the component.
22+
*/
23+
public function render(): View
24+
{
25+
return $this->view('root::components.copyable', [
26+
'text' => $this->text,
27+
'value' => $this->value,
28+
]);
29+
}
30+
}

0 commit comments

Comments
 (0)