1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use *;
/// The fewest placeholder lines a skeleton block will render.
const SKELETON_LINES_MIN: usize = 1;
/// The most placeholder lines a skeleton block will render.
///
/// A loading placeholder is a stand-in for a short block of content; past
/// a handful of lines a skeleton stops reading as a placeholder and the
/// height is better owned by an explicit `euv_loading` indicator.
const SKELETON_LINES_MAX: usize = 8;
/// The width applied to skeleton lines when the `width` prop is unusable.
const SKELETON_WIDTH_DEFAULT: &str = "100%";
/// The border radius applied to skeleton lines when `rounded` is true.
///
/// The design system is square by default; rounding is opt-in per block so
/// a caller can match a circular avatar or a pill-shaped chip without the
/// rest of the component library losing its `border-radius: 0px` rule.
const SKELETON_RADIUS: &str = "2px";
/// Clamps a requested line count into the renderable `1..=8` range.
///
/// A `0` request still draws one line: an empty block reads as a layout
/// bug rather than as loading, and the caller who meant to hide it should
/// unmount the component instead of rendering nothing.
///
/// # Arguments
///
/// - `usize` - The requested number of placeholder lines.
///
/// # Returns
///
/// - `usize` - The line count clamped into the `1..=8` range.
/// A loading placeholder shown while real content is still being fetched.
///
/// Renders a `c_euv_skeleton` block holding one `c_euv_skeleton_line` per
/// requested line, each carrying an inline `width` (and `height` when one
/// is supplied). The pulse is not animated here: the shipped
/// `c_euv_skeleton_line` class already references the global
/// `euv-pulse` keyframe, so the shimmer runs off the shared animation
/// rather than a per-instance one. The `rounded` signal drives the
/// `border-radius` override through the same inline style.
///
/// # Arguments
///
/// - `VirtualNode<EuvSkeletonProps>` - The props node containing lines, width, height and rounded.
///
/// # Returns
///
/// - `VirtualNode` - The skeleton placeholder virtual DOM tree.
/// Renders one placeholder line with its inline geometry.
///
/// The declarations are concatenated into a single style string rather
/// than stacked as repeated `style:` attributes: only the top-level
/// attributes of an element are read as attributes, so a declaration
/// nested inside a conditional child block would be dropped. `height` is
/// omitted entirely when the prop is empty, leaving the stylesheet default
/// in charge.
///
/// # Arguments
///
/// - `usize` - The zero-based position of this line, used as its key.
/// - `&'static str` - The requested width, e.g. `"60%"`.
/// - `&'static str` - The requested height, e.g. `"24px"`.
/// - `Signal<bool>` - Whether the line is drawn with rounded corners.
///
/// # Returns
///
/// - `VirtualNode` - The placeholder line virtual DOM tree.
/// Normalises the `width` prop into a usable CSS length.
///
/// Only percentages are accepted: the skeleton is a placeholder for a
/// block of in-flow text, and an arbitrary length would let it overflow
/// its container. An empty or non-percentage value falls back to
/// `100%`.
///
/// # Arguments
///
/// - `&'static str` - The requested width, e.g. `"60%"`.
///
/// # Returns
///
/// - `&'static str` - The width to apply, ending in `%`.