@jack-henry/jh-elements 2.0.0-beta.8
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.
- package/LICENSE +201 -0
- package/NOTICE +26 -0
- package/README.md +13 -0
- package/components/badge/badge.js +73 -0
- package/components/button/button.js +953 -0
- package/components/card/card.js +333 -0
- package/components/checkbox/checkbox.js +601 -0
- package/components/checkbox-group/checkbox-group.js +241 -0
- package/components/divider/divider.js +91 -0
- package/components/icon/icon.js +96 -0
- package/components/input/input.js +1245 -0
- package/components/input-email/input-email.js +18 -0
- package/components/input-password/input-password.js +153 -0
- package/components/input-search/input-search.js +41 -0
- package/components/input-telephone/input-telephone.js +18 -0
- package/components/input-textarea/input-textarea.js +374 -0
- package/components/input-url/input-url.js +31 -0
- package/components/list-group/list-group.js +103 -0
- package/components/list-item/list-item.js +350 -0
- package/components/menu/menu.js +60 -0
- package/components/notification/notification.js +327 -0
- package/components/progress/progress.js +417 -0
- package/components/radio/radio.js +422 -0
- package/components/radio-group/radio-group.js +400 -0
- package/components/switch/switch.js +316 -0
- package/components/table/table.js +367 -0
- package/components/table-data-cell/table-data-cell.js +107 -0
- package/components/table-header-cell/table-header-cell.js +321 -0
- package/components/table-row/table-row.js +52 -0
- package/components/tag/tag.js +422 -0
- package/components/tag-group/tag-group.js +57 -0
- package/components/toast/toast.js +172 -0
- package/components/toast-controller/toast-controller.js +122 -0
- package/components/tooltip/tooltip.js +498 -0
- package/custom-elements.json +6864 -0
- package/index.d.ts +69 -0
- package/jsconfig.json +9 -0
- package/package.json +52 -0
- package/utils/themeProvider.js +32 -0
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 Jack Henry
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
import { LitElement, css, html } from 'lit';
|
|
6
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @cssprop --jh-progress-label-color - The label text color. Defaults to `--jh-color-content-primary-enabled`.
|
|
10
|
+
* @cssprop --jh-progress-value-color - The value text color. Defaults to `--jh-color-content-secondary-enabled`.
|
|
11
|
+
* @cssprop --jh-progress-track-color - The track color. Defaults to `--jh-color-control-enabled`.
|
|
12
|
+
* @cssprop --jh-progress-track-border-radius - The track border-radius. Defaults to `--jh-border-radius-50`.
|
|
13
|
+
* @cssprop --jh-progress-indicator-color - The indicator color. Defaults to `--jh-color-content-brand-enabled`.
|
|
14
|
+
* @customElement jh-progress
|
|
15
|
+
*/
|
|
16
|
+
export class JhProgress extends LitElement {
|
|
17
|
+
/** @type {ElementInternals} */
|
|
18
|
+
#internals;
|
|
19
|
+
|
|
20
|
+
/** @type {string} */
|
|
21
|
+
#label;
|
|
22
|
+
|
|
23
|
+
static get styles() {
|
|
24
|
+
return css`
|
|
25
|
+
@keyframes indicator {
|
|
26
|
+
from {
|
|
27
|
+
margin-left: -45%;
|
|
28
|
+
}
|
|
29
|
+
to {
|
|
30
|
+
margin-left: 95%;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
@keyframes spin {
|
|
34
|
+
100% {
|
|
35
|
+
transform: rotate(360deg);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
:host {
|
|
39
|
+
font-family: var(--jh-font-helper-regular-font-family);
|
|
40
|
+
font-weight: var(--jh-font-helper-regular-font-weight);
|
|
41
|
+
font-size: var(--jh-font-helper-regular-font-size);
|
|
42
|
+
line-height: var(--jh-font-helper-regular-line-height);
|
|
43
|
+
display: block;
|
|
44
|
+
width: 100%;
|
|
45
|
+
}
|
|
46
|
+
.text-content {
|
|
47
|
+
color: var(
|
|
48
|
+
--jh-progress-label-color,
|
|
49
|
+
var(--jh-color-content-primary-enabled)
|
|
50
|
+
);
|
|
51
|
+
margin-bottom: var(--jh-dimension-100);
|
|
52
|
+
}
|
|
53
|
+
label {
|
|
54
|
+
overflow-wrap: anywhere;
|
|
55
|
+
word-break: normal;
|
|
56
|
+
}
|
|
57
|
+
span {
|
|
58
|
+
color: var(
|
|
59
|
+
--jh-progress-value-color,
|
|
60
|
+
var(--jh-color-content-secondary-enabled)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
/* Linear */
|
|
64
|
+
:host([label][type='linear']) .text-content {
|
|
65
|
+
display: flex;
|
|
66
|
+
justify-content: space-between;
|
|
67
|
+
}
|
|
68
|
+
:host([label=''][type='linear']) .text-content,
|
|
69
|
+
:host(:not([label])[type='linear']) .text-content {
|
|
70
|
+
display: flex;
|
|
71
|
+
justify-content: flex-end;
|
|
72
|
+
}
|
|
73
|
+
span {
|
|
74
|
+
width: auto;
|
|
75
|
+
}
|
|
76
|
+
span.has-label {
|
|
77
|
+
margin-left: var(--jh-dimension-200);
|
|
78
|
+
}
|
|
79
|
+
.linear-progress-bar {
|
|
80
|
+
background-color: var(
|
|
81
|
+
--jh-progress-track-color,
|
|
82
|
+
var(--jh-color-control-enabled)
|
|
83
|
+
);
|
|
84
|
+
border-radius: var(
|
|
85
|
+
--jh-progress-track-border-radius,
|
|
86
|
+
var(--jh-border-radius-50)
|
|
87
|
+
);
|
|
88
|
+
overflow: hidden;
|
|
89
|
+
}
|
|
90
|
+
:host([size='small']) .linear-progress-bar {
|
|
91
|
+
height: var(--jh-dimension-50);
|
|
92
|
+
}
|
|
93
|
+
:host([size='medium']) .linear-progress-bar {
|
|
94
|
+
height: var(--jh-dimension-100);
|
|
95
|
+
}
|
|
96
|
+
:host([size='large']) .linear-progress-bar {
|
|
97
|
+
height: var(--jh-dimension-200);
|
|
98
|
+
}
|
|
99
|
+
:host .linear-progress-bar-value {
|
|
100
|
+
background-color: var(
|
|
101
|
+
--jh-progress-indicator-color,
|
|
102
|
+
var(--jh-color-content-brand-enabled)
|
|
103
|
+
);
|
|
104
|
+
height: 100%;
|
|
105
|
+
}
|
|
106
|
+
/* Circular */
|
|
107
|
+
:host([type='circular']) .container {
|
|
108
|
+
display: flex;
|
|
109
|
+
flex-direction: column-reverse;
|
|
110
|
+
align-items: center;
|
|
111
|
+
}
|
|
112
|
+
:host([type='circular']) .text-content {
|
|
113
|
+
margin-top: var(--jh-dimension-200);
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
}
|
|
117
|
+
svg {
|
|
118
|
+
transform: rotate(-90deg);
|
|
119
|
+
width: var(--progress-size);
|
|
120
|
+
height: var(--progress-size);
|
|
121
|
+
overflow: visible;
|
|
122
|
+
}
|
|
123
|
+
:host([size='small']) svg {
|
|
124
|
+
--progress-size: var(--jh-dimension-300);
|
|
125
|
+
}
|
|
126
|
+
:host([size='medium']) svg {
|
|
127
|
+
--progress-size: var(--jh-dimension-400);
|
|
128
|
+
margin-bottom: 1px;
|
|
129
|
+
}
|
|
130
|
+
:host([size='large']) svg {
|
|
131
|
+
--progress-size: var(--jh-dimension-800);
|
|
132
|
+
margin-bottom: 2px;
|
|
133
|
+
}
|
|
134
|
+
circle {
|
|
135
|
+
transform-origin: 50% 50%;
|
|
136
|
+
fill: none;
|
|
137
|
+
}
|
|
138
|
+
.circular-progress-bar {
|
|
139
|
+
stroke: var(--jh-progress-track-color, var(--jh-color-control-enabled));
|
|
140
|
+
stroke-dashoffset: 0;
|
|
141
|
+
}
|
|
142
|
+
.circular-progress-bar-value {
|
|
143
|
+
stroke: var(
|
|
144
|
+
--jh-progress-indicator-color,
|
|
145
|
+
var(--jh-color-content-brand-enabled)
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
:host([size='small']) circle {
|
|
149
|
+
stroke-width: 1;
|
|
150
|
+
stroke-dasharray: 37.8px;
|
|
151
|
+
}
|
|
152
|
+
:host([size='medium']) circle {
|
|
153
|
+
stroke-width: 2;
|
|
154
|
+
stroke-dasharray: 50.3px;
|
|
155
|
+
}
|
|
156
|
+
:host([size='large']) circle {
|
|
157
|
+
stroke-width: 4;
|
|
158
|
+
stroke-dasharray: 100.8px;
|
|
159
|
+
}
|
|
160
|
+
:host([type='circular']) div {
|
|
161
|
+
text-align: center;
|
|
162
|
+
}
|
|
163
|
+
/* Indeterminate */
|
|
164
|
+
:host([indeterminate]) .linear-progress-bar-value {
|
|
165
|
+
width: 50%;
|
|
166
|
+
animation: 1.2s cubic-bezier(0.65, 0, 0.35, 1) infinite alternate
|
|
167
|
+
indicator;
|
|
168
|
+
}
|
|
169
|
+
:host([indeterminate]) svg {
|
|
170
|
+
transform: none;
|
|
171
|
+
animation: spin 0.75s linear infinite;
|
|
172
|
+
}
|
|
173
|
+
`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
static get properties() {
|
|
177
|
+
return {
|
|
178
|
+
/** Sets an `aria-label` to assist screen reader users when no visible label is present. */
|
|
179
|
+
accessibleLabel: { type: String, attribute: 'accessible-label' },
|
|
180
|
+
/** Sets `aria-valuetext` on progress indicator to provide text alternative of `aria-valuenow`. To be used when progress cannot be represented as a number. */
|
|
181
|
+
accessibleValueText: { type: String, attribute: 'accessible-valuetext' },
|
|
182
|
+
/** Hides the `value` text. */
|
|
183
|
+
hideValue: { type: Boolean, attribute: 'hide-value' },
|
|
184
|
+
/** Sets the indeterminate state on progress. To be used when progress cannot be calculated. */
|
|
185
|
+
indeterminate: { type: Boolean, reflect: true },
|
|
186
|
+
/**
|
|
187
|
+
* Provides information about the item which triggered the progress component.
|
|
188
|
+
*/
|
|
189
|
+
label: { type: String, reflect: true },
|
|
190
|
+
/** Defines the maximum allowed value and sets `aria-valuemax` attribute. */
|
|
191
|
+
max: { type: Number },
|
|
192
|
+
/** Defines the minimum allowed value and sets `aria-valuemin` attribute. */
|
|
193
|
+
min: { type: Number },
|
|
194
|
+
/** Sets the size of the progress component. */
|
|
195
|
+
size: { type: String, reflect: true },
|
|
196
|
+
/** Determines the style of progress to display. */
|
|
197
|
+
type: { type: String, reflect: true },
|
|
198
|
+
/** Specifies how much of the task has been completed. This value is used to calculate the percentage complete based on the min and max values. */
|
|
199
|
+
value: { type: Number },
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
constructor() {
|
|
204
|
+
super();
|
|
205
|
+
this.#internals = this.attachInternals();
|
|
206
|
+
/** @type {Boolean} */
|
|
207
|
+
this.indeterminate = false;
|
|
208
|
+
/** @type {?string} */
|
|
209
|
+
this.label = null;
|
|
210
|
+
/** @type {'small'|'medium'|'large'} */
|
|
211
|
+
this.size = 'medium';
|
|
212
|
+
/** @type {'linear'|'circular'} */
|
|
213
|
+
this.type = 'linear';
|
|
214
|
+
/** @type {Boolean} */
|
|
215
|
+
this.hideValue = false;
|
|
216
|
+
/** @type {?string} */
|
|
217
|
+
this.#internals.ariaLabel;
|
|
218
|
+
/** @type {number} */
|
|
219
|
+
this.#internals.ariaValueMax;
|
|
220
|
+
/** @type {number} */
|
|
221
|
+
this.#internals.ariaValueMin;
|
|
222
|
+
/** @type {?number} */
|
|
223
|
+
this.#internals.ariaValueNow;
|
|
224
|
+
/** @type {?string} */
|
|
225
|
+
this.#internals.ariaValueText;
|
|
226
|
+
/** @type {?string} */
|
|
227
|
+
this.#internals.role = 'progressbar';
|
|
228
|
+
/** @type {?string} */
|
|
229
|
+
this.accessibleLabel = null;
|
|
230
|
+
/** @type {?number} */
|
|
231
|
+
this.max = 100;
|
|
232
|
+
/** @type {?number} */
|
|
233
|
+
this.min = 0;
|
|
234
|
+
/** @type {?number} */
|
|
235
|
+
this.value = 0;
|
|
236
|
+
/** @type {?string} */
|
|
237
|
+
this.accessibleValueText = null;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
connectedCallback() {
|
|
241
|
+
super.connectedCallback();
|
|
242
|
+
let observer = new MutationObserver(this.#updateState.bind(this));
|
|
243
|
+
observer.observe(this, { attributeFilter: ['indeterminate'] });
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
#updateState(){
|
|
247
|
+
if (this.indeterminate) {
|
|
248
|
+
this.value = null;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Shared setter for elementInternals properties
|
|
253
|
+
#setAttribute(ariaAttribute, newValue) {
|
|
254
|
+
const oldValue = this.#internals[ariaAttribute];
|
|
255
|
+
|
|
256
|
+
if (newValue !== oldValue) {
|
|
257
|
+
this.#internals[ariaAttribute] = newValue;
|
|
258
|
+
}
|
|
259
|
+
this.requestUpdate(ariaAttribute, oldValue);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
get label() {
|
|
263
|
+
return this.#label;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
set label(newValue) {
|
|
267
|
+
const oldValue = this.label;
|
|
268
|
+
if (newValue !== oldValue) {
|
|
269
|
+
this.#label = newValue;
|
|
270
|
+
if (this.accessibleLabel === null) {
|
|
271
|
+
this.accessibleLabel = newValue;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
this.requestUpdate('label', oldValue);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
get accessibleLabel() {
|
|
278
|
+
return this.#internals.ariaLabel;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
set accessibleLabel(newValue) {
|
|
282
|
+
this.#setAttribute('ariaLabel', newValue);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
get min() {
|
|
286
|
+
return this.#internals.ariaValueMin;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
set min(newValue) {
|
|
290
|
+
this.#setAttribute('ariaValueMin', newValue);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
get max() {
|
|
294
|
+
return this.#internals.ariaValueMax;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
set max(newValue) {
|
|
298
|
+
this.#setAttribute('ariaValueMax', newValue);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
get accessibleValueText() {
|
|
302
|
+
return this.#internals.ariaValueText;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
set accessibleValueText(newValue) {
|
|
306
|
+
this.#setAttribute('ariaValueText', newValue);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
get value() {
|
|
310
|
+
return this.#internals.ariaValueNow;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
set value(newValue) {
|
|
314
|
+
this.#setAttribute('ariaValueNow', newValue);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
#getCircularIndicator(size, indeterminate, percentage) {
|
|
318
|
+
let percentComplete;
|
|
319
|
+
|
|
320
|
+
if (indeterminate) {
|
|
321
|
+
percentComplete = 75;
|
|
322
|
+
} else if (percentage === null) {
|
|
323
|
+
percentComplete = 0;
|
|
324
|
+
} else {
|
|
325
|
+
percentComplete = percentage;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const circle = {
|
|
329
|
+
// Numbers represent radius, x&y axis, and circumference
|
|
330
|
+
small: [6, 6, 37.8],
|
|
331
|
+
medium: [8, 8, 50.3],
|
|
332
|
+
large: [16, 16, 100.8],
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const [r, axis, c] = circle[size];
|
|
336
|
+
|
|
337
|
+
let percentOfCircleFilled = c - (c * Number(percentComplete)) / 100;
|
|
338
|
+
|
|
339
|
+
return html`
|
|
340
|
+
<svg>
|
|
341
|
+
<circle
|
|
342
|
+
class="circular-progress-bar"
|
|
343
|
+
r=${r}
|
|
344
|
+
cx=${axis}
|
|
345
|
+
cy=${axis}
|
|
346
|
+
c=${c}
|
|
347
|
+
></circle>
|
|
348
|
+
<circle
|
|
349
|
+
class="circular-progress-bar-value"
|
|
350
|
+
r=${r}
|
|
351
|
+
cx=${axis}
|
|
352
|
+
cy=${axis}
|
|
353
|
+
c=${c}
|
|
354
|
+
style="stroke-dashoffset:${percentOfCircleFilled}px"
|
|
355
|
+
></circle>
|
|
356
|
+
</svg>
|
|
357
|
+
`;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
#getLinearIndicator(percentage) {
|
|
361
|
+
return html`
|
|
362
|
+
<div class="linear-progress-bar">
|
|
363
|
+
<div
|
|
364
|
+
class="linear-progress-bar-value"
|
|
365
|
+
style=${ifDefined(
|
|
366
|
+
this.indeterminate ? null : `width:${percentage || 0}%`
|
|
367
|
+
)}
|
|
368
|
+
></div>
|
|
369
|
+
</div>
|
|
370
|
+
`;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
render() {
|
|
374
|
+
let indicator;
|
|
375
|
+
let value;
|
|
376
|
+
let valueStyles;
|
|
377
|
+
let label;
|
|
378
|
+
|
|
379
|
+
let percentage = Math.round(
|
|
380
|
+
((+this.value - +this.min) / (+this.max - +this.min)) * 100
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
if (this.label) {
|
|
384
|
+
label = html`<label>${this.label}</label>`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
if (this.type === 'linear') {
|
|
388
|
+
indicator = this.#getLinearIndicator(percentage);
|
|
389
|
+
} else if (this.type === 'circular') {
|
|
390
|
+
indicator = this.#getCircularIndicator(
|
|
391
|
+
this.size,
|
|
392
|
+
this.indeterminate,
|
|
393
|
+
percentage
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (this.value && !this.hideValue && !this.indeterminate) {
|
|
398
|
+
if (this.label && this.type === 'linear') {
|
|
399
|
+
valueStyles = 'has-label';
|
|
400
|
+
}
|
|
401
|
+
value = html`
|
|
402
|
+
<span class=${ifDefined(valueStyles)}>${percentage + '%'}</span>
|
|
403
|
+
`;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return html`
|
|
407
|
+
<div class="container">
|
|
408
|
+
${this.label || (this.value && !this.hideValue)
|
|
409
|
+
? html`<div class="text-content">${label} ${value}</div>`
|
|
410
|
+
: null}
|
|
411
|
+
${indicator}
|
|
412
|
+
</div>
|
|
413
|
+
`;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
customElements.define('jh-progress', JhProgress);
|