Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace Termwind;
6
 
7
use Closure;
8
use Symfony\Component\Console\Output\ConsoleOutput;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use Termwind\Components\Element;
11
use Termwind\Exceptions\InvalidChild;
12
 
13
/**
14
 * @internal
15
 */
16
final class Termwind
17
{
18
    /**
19
     * The implementation of the output.
20
     */
21
    private static OutputInterface|null $renderer;
22
 
23
    /**
24
     * Sets the renderer implementation.
25
     */
26
    public static function renderUsing(OutputInterface|null $renderer): void
27
    {
28
        self::$renderer = $renderer ?? new ConsoleOutput();
29
    }
30
 
31
    /**
32
     * Creates a div element instance.
33
     *
34
     * @param  array<int, Element|string>|string  $content
35
     * @param  array<string, mixed>  $properties
36
     */
37
    public static function div(array|string $content = '', string $styles = '', array $properties = []): Components\Div
38
    {
39
        $content = self::prepareElements($content, $styles);
40
 
41
        return Components\Div::fromStyles(
42
            self::getRenderer(), $content, $styles, $properties
43
        );
44
    }
45
 
46
    /**
47
     * Creates a paragraph element instance.
48
     *
49
     * @param  array<int, Element|string>|string  $content
50
     * @param  array<string, mixed>  $properties
51
     */
52
    public static function paragraph(array|string $content = '', string $styles = '', array $properties = []): Components\Paragraph
53
    {
54
        $content = self::prepareElements($content, $styles);
55
 
56
        return Components\Paragraph::fromStyles(
57
            self::getRenderer(), $content, $styles, $properties
58
        );
59
    }
60
 
61
    /**
62
     * Creates a span element instance with the given style.
63
     *
64
     * @param  array<int, Element|string>|string  $content
65
     * @param  array<string, mixed>  $properties
66
     */
67
    public static function span(array|string $content = '', string $styles = '', array $properties = []): Components\Span
68
    {
69
        $content = self::prepareElements($content, $styles);
70
 
71
        return Components\Span::fromStyles(
72
            self::getRenderer(), $content, $styles, $properties
73
        );
74
    }
75
 
76
    /**
77
     * Creates an element instance with raw content.
78
     *
79
     * @param  array<int, Element|string>|string  $content
80
     */
81
    public static function raw(array|string $content = ''): Components\Raw
82
    {
83
        return Components\Raw::fromStyles(
84
            self::getRenderer(), $content
85
        );
86
    }
87
 
88
    /**
89
     * Creates an anchor element instance with the given style.
90
     *
91
     * @param  array<int, Element|string>|string  $content
92
     * @param  array<string, mixed>  $properties
93
     */
94
    public static function anchor(array|string $content = '', string $styles = '', array $properties = []): Components\Anchor
95
    {
96
        $content = self::prepareElements($content, $styles);
97
 
98
        return Components\Anchor::fromStyles(
99
            self::getRenderer(), $content, $styles, $properties
100
        );
101
    }
102
 
103
    /**
104
     * Creates an unordered list instance.
105
     *
106
     * @param  array<int, string|Element>  $content
107
     * @param  array<string, mixed>  $properties
108
     */
109
    public static function ul(array $content = [], string $styles = '', array $properties = []): Components\Ul
110
    {
111
        $ul = Components\Ul::fromStyles(
112
            self::getRenderer(), '', $styles, $properties
113
        );
114
 
115
        $content = self::prepareElements(
116
            $content,
117
            $styles,
118
            static function ($li) use ($ul): string|Element {
119
                if (is_string($li)) {
120
                    return $li;
121
                }
122
 
123
                if (! $li instanceof Components\Li) {
124
                    throw new InvalidChild('Unordered lists only accept `li` as child');
125
                }
126
 
127
                return match (true) {
128
                    $li->hasStyle('list-none') => $li,
129
                    $ul->hasStyle('list-none') => $li->addStyle('list-none'),
130
                    $ul->hasStyle('list-square') => $li->addStyle('list-square'),
131
                    $ul->hasStyle('list-disc') => $li->addStyle('list-disc'),
132
                    default => $li->addStyle('list-none'),
133
                };
134
            }
135
        );
136
 
137
        return $ul->setContent($content);
138
    }
139
 
140
    /**
141
     * Creates an ordered list instance.
142
     *
143
     * @param  array<int, string|Element>  $content
144
     * @param  array<string, mixed>  $properties
145
     */
146
    public static function ol(array $content = [], string $styles = '', array $properties = []): Components\Ol
147
    {
148
        $ol = Components\Ol::fromStyles(
149
            self::getRenderer(), '', $styles, $properties
150
        );
151
 
152
        $index = 0;
153
 
154
        $content = self::prepareElements(
155
            $content,
156
            $styles,
157
            static function ($li) use ($ol, &$index): string|Element {
158
                if (is_string($li)) {
159
                    return $li;
160
                }
161
 
162
                if (! $li instanceof Components\Li) {
163
                    throw new InvalidChild('Ordered lists only accept `li` as child');
164
                }
165
 
166
                return match (true) {
167
                    $li->hasStyle('list-none') => $li->addStyle('list-none'),
168
                    $ol->hasStyle('list-none') => $li->addStyle('list-none'),
169
                    $ol->hasStyle('list-decimal') => $li->addStyle('list-decimal-'.(++$index)),
170
                    default => $li->addStyle('list-none'),
171
                };
172
            }
173
        );
174
 
175
        return $ol->setContent($content);
176
    }
177
 
178
    /**
179
     * Creates a list item instance.
180
     *
181
     * @param  array<int, Element|string>|string  $content
182
     * @param  array<string, mixed>  $properties
183
     */
184
    public static function li(array|string $content = '', string $styles = '', array $properties = []): Components\Li
185
    {
186
        $content = self::prepareElements($content, $styles);
187
 
188
        return Components\Li::fromStyles(
189
            self::getRenderer(), $content, $styles, $properties
190
        );
191
    }
192
 
193
    /**
194
     * Creates a description list instance.
195
     *
196
     * @param  array<int, string|Element>  $content
197
     * @param  array<string, mixed>  $properties
198
     */
199
    public static function dl(array $content = [], string $styles = '', array $properties = []): Components\Dl
200
    {
201
        $content = self::prepareElements(
202
            $content,
203
            $styles,
204
            static function ($element): string|Element {
205
                if (is_string($element)) {
206
                    return $element;
207
                }
208
 
209
                if (! $element instanceof Components\Dt && ! $element instanceof Components\Dd) {
210
                    throw new InvalidChild('Description lists only accept `dt` and `dd` as children');
211
                }
212
 
213
                return $element;
214
            }
215
        );
216
 
217
        return Components\Dl::fromStyles(
218
            self::getRenderer(), $content, $styles, $properties
219
        );
220
    }
221
 
222
    /**
223
     * Creates a description term instance.
224
     *
225
     * @param  array<int, Element|string>|string  $content
226
     * @param  array<string, mixed>  $properties
227
     */
228
    public static function dt(array|string $content = '', string $styles = '', array $properties = []): Components\Dt
229
    {
230
        $content = self::prepareElements($content, $styles);
231
 
232
        return Components\Dt::fromStyles(
233
            self::getRenderer(), $content, $styles, $properties
234
        );
235
    }
236
 
237
    /**
238
     * Creates a description details instance.
239
     *
240
     * @param  array<int, Element|string>|string  $content
241
     * @param  array<string, mixed>  $properties
242
     */
243
    public static function dd(array|string $content = '', string $styles = '', array $properties = []): Components\Dd
244
    {
245
        $content = self::prepareElements($content, $styles);
246
 
247
        return Components\Dd::fromStyles(
248
            self::getRenderer(), $content, $styles, $properties
249
        );
250
    }
251
 
252
    /**
253
     * Creates a horizontal rule instance.
254
     *
255
     * @param  array<string, mixed>  $properties
256
     */
257
    public static function hr(string $styles = '', array $properties = []): Components\Hr
258
    {
259
        return Components\Hr::fromStyles(
260
            self::getRenderer(), '', $styles, $properties
261
        );
262
    }
263
 
264
    /**
265
     * Creates an break line element instance.
266
     *
267
     * @param  array<string, mixed>  $properties
268
     */
269
    public static function breakLine(string $styles = '', array $properties = []): Components\BreakLine
270
    {
271
        return Components\BreakLine::fromStyles(
272
            self::getRenderer(), '', $styles, $properties
273
        );
274
    }
275
 
276
    /**
277
     * Gets the current renderer instance.
278
     */
279
    public static function getRenderer(): OutputInterface
280
    {
281
        return self::$renderer ??= new ConsoleOutput();
282
    }
283
 
284
    /**
285
     * Convert child elements to a string.
286
     *
287
     * @param  array<int, string|Element>|string  $elements
288
     * @return array<int, string|Element>
289
     */
290
    private static function prepareElements($elements, string $styles = '', Closure|null $callback = null): array
291
    {
292
        if ($callback === null) {
293
            $callback = static fn ($element): string|Element => $element;
294
        }
295
 
296
        $elements = is_array($elements) ? $elements : [$elements];
297
 
298
        return array_map($callback, $elements);
299
    }
300
}