@threadlabs/looma 0.14.1 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,186 @@
1
+ <template component="ui-meter">
2
+ <defs>
3
+ <prop name="value" type="number" default="0"
4
+ >How far along, from 0 to max. A value outside that range draws at the nearer end: below 0 is an empty track, above max a full bar.</prop>
5
+ <prop name="max" type="number" default="1"
6
+ >The value of a full bar, as on a native meter: 1 for a fraction, or the whole amount (a total, a count of items) with value as the part of it. Must be
7
+ above 0; otherwise the bar is empty.</prop>
8
+ <prop name="tone" type="neutral | accent | info | success | warning | danger" default="neutral"
9
+ >Which colour the filled part speaks in, as on Badge: neutral is a quiet grey, accent draws the eye, and info, success, warning, and danger mark a state
10
+ (such as nothing yet, partial, complete, or needs attention). Colour alone says nothing to assistive technology or in forced colours, so say the state in
11
+ valueText or in text beside the meter too.</prop>
12
+ <prop name="size" type="sm | md" default="md"
13
+ >Thickness. sm is a thin bar that sits in a line of text, such as a table cell beside an amount; md stands on its own.</prop>
14
+ <prop name="segments" type="number" default="0"
15
+ >How many equal segments to draw the bar as, from 2 to 12, for a count of steps: set max to the same number and value to the steps done, so whole segments
16
+ fill, and say the step in valueText ("Shipped, step 4 of 6"). A value between steps fills part of a segment. 0 draws one continuous bar, as does any other
17
+ number.</prop>
18
+ <prop name="label" type="string" default=""
19
+ >What the meter measures, as its accessible name ("Collected"). Leave it empty only when aria-labelledby names the meter from visible text.</prop>
20
+ <prop name="valueText" type="string" default=""
21
+ >The value as assistive technology reads it ("$750 of $1,240 collected", "3 of 5 done, overdue"). Empty reads the percentage.</prop>
22
+ <!-- Derived as it renders, so every render path, a server render included, draws the bar and states its value without JavaScript. -->
23
+ <computed name="amount" from="clamp(0, value, max)"></computed>
24
+ <computed name="percent" from="{ true: amount / max * 100, false: 0 }[format('%s', max > 0)]"></computed>
25
+ <!-- percent rounded half up, for the text: round() on a derived number does not compile to Vue yet. -->
26
+ <computed name="whole" from="percent + 0.5 - (percent + 0.5) % 1"></computed>
27
+ </defs>
28
+ <span
29
+ role="meter"
30
+ aria-valuemin="0"
31
+ :aria-valuemax="max"
32
+ :aria-valuenow="amount"
33
+ :aria-valuetext="{ true: valueText, false: format('%s%', whole) }[format('%s', valueText != '')]"
34
+ :aria-label="{ true: label, false: null }[format('%s', label != '')]"
35
+ :data-ui-meter-segments="{ true: segments, false: null }[format('%s', segments > 1)]"
36
+ >
37
+ <span class="fill" style:inline-size="format('%s%', percent)"></span>
38
+ </span>
39
+ <style>
40
+ /* How far along something is: a track, filled from the start in the tone's colour. The track is a
41
+ quiet border colour, so an empty meter still shows; every tone's fill keeps 3:1 against the
42
+ track and the page. */
43
+ @property --ui-meter-inline-size {
44
+ syntax: "*";
45
+ inherits: false;
46
+ }
47
+
48
+ :host {
49
+ --_meter-fill: var(--ui-text-muted);
50
+
51
+ display: inline-block;
52
+ flex: none;
53
+ vertical-align: middle;
54
+ inline-size: var(--ui-meter-inline-size, 8rem);
55
+ max-inline-size: 100%;
56
+ block-size: var(--ui-space-2);
57
+ overflow: hidden;
58
+ border-radius: var(--ui-radius-round);
59
+ background: var(--ui-border);
60
+ /* Unseen until forced colours draw it, where the track's own colour is gone. */
61
+ outline: 1px solid transparent;
62
+ }
63
+
64
+ :host-state([size="sm"]) {
65
+ inline-size: var(--ui-meter-inline-size, 5rem);
66
+ block-size: var(--ui-space-1);
67
+ }
68
+
69
+ .fill {
70
+ display: block;
71
+ block-size: 100%;
72
+ background: var(--_meter-fill);
73
+ }
74
+
75
+ :host-state([tone="accent"]) {
76
+ --_meter-fill: var(--ui-accent-solid);
77
+ }
78
+
79
+ :host-state([tone="info"]) {
80
+ --_meter-fill: var(--ui-info-solid);
81
+ }
82
+
83
+ :host-state([tone="success"]) {
84
+ --_meter-fill: var(--ui-success-solid);
85
+ }
86
+
87
+ :host-state([tone="warning"]) {
88
+ --_meter-fill: var(--ui-warning-solid);
89
+ }
90
+
91
+ :host-state([tone="danger"]) {
92
+ --_meter-fill: var(--ui-danger-solid);
93
+ }
94
+
95
+ /* Segments: the track and its fill show through a mask of equal segments with a gap between them.
96
+ A mask over the whole meter, rather than one element per segment, because the expression
97
+ language has no range to render N elements from, and one mask lines the fill up with the track
98
+ for free. Each period is a segment and the gap after it; N periods span the track plus one
99
+ trailing gap, so the segments sit symmetrically and right to left needs nothing of its own.
100
+ The count arrives as an attribute, not an inline custom property (which would add a style
101
+ attribute to every meter), so a continuous meter renders exactly as before, and the rules below
102
+ turn it into a number. That caps it at 12, until attr() with a type reads any count in every engine. */
103
+ :host[data-ui-meter-segments="2"] {
104
+ --_segments: 2;
105
+ }
106
+
107
+ :host[data-ui-meter-segments="3"] {
108
+ --_segments: 3;
109
+ }
110
+
111
+ :host[data-ui-meter-segments="4"] {
112
+ --_segments: 4;
113
+ }
114
+
115
+ :host[data-ui-meter-segments="5"] {
116
+ --_segments: 5;
117
+ }
118
+
119
+ :host[data-ui-meter-segments="6"] {
120
+ --_segments: 6;
121
+ }
122
+
123
+ :host[data-ui-meter-segments="7"] {
124
+ --_segments: 7;
125
+ }
126
+
127
+ :host[data-ui-meter-segments="8"] {
128
+ --_segments: 8;
129
+ }
130
+
131
+ :host[data-ui-meter-segments="9"] {
132
+ --_segments: 9;
133
+ }
134
+
135
+ :host[data-ui-meter-segments="10"] {
136
+ --_segments: 10;
137
+ }
138
+
139
+ :host[data-ui-meter-segments="11"] {
140
+ --_segments: 11;
141
+ }
142
+
143
+ :host[data-ui-meter-segments="12"] {
144
+ --_segments: 12;
145
+ }
146
+
147
+ :host[data-ui-meter-segments] {
148
+ --_meter-gap: var(--ui-space-1);
149
+ --_meter-period: calc((100% + var(--_meter-gap)) / var(--_segments));
150
+ --_meter-segment: calc(var(--_meter-period) - var(--_meter-gap));
151
+
152
+ mask-image: repeating-linear-gradient(to right, #000 0 var(--_meter-segment), transparent 0 var(--_meter-period));
153
+ }
154
+
155
+ :host-state([size="sm"])[data-ui-meter-segments] {
156
+ --_meter-gap: var(--ui-space-0-5);
157
+ }
158
+
159
+ /* Forced colours drop backgrounds: draw the fill in the text colour inside the outlined track. */
160
+ @media (forced-colors: active) {
161
+ .fill {
162
+ forced-color-adjust: none;
163
+ background: CanvasText;
164
+ }
165
+
166
+ /* The mask clips the track's outline, so each segment draws its own: the inset shadow draws the
167
+ top and bottom edges and the gradient the ends. */
168
+ :host[data-ui-meter-segments] {
169
+ forced-color-adjust: none;
170
+ background: repeating-linear-gradient(
171
+ to right,
172
+ CanvasText 0 1px,
173
+ Canvas 0 calc(var(--_meter-segment) - 1px),
174
+ CanvasText 0 var(--_meter-segment),
175
+ transparent 0 var(--_meter-period)
176
+ );
177
+ box-shadow: inset 0 0 0 1px CanvasText;
178
+ }
179
+ }
180
+
181
+ /* A component that sets its display still honours the hidden attribute on its root. */
182
+ :host[hidden] {
183
+ display: none;
184
+ }
185
+ </style>
186
+ </template>