superdesk-ui-framework 5.0.2 → 5.0.4
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/.mocharc.json +1 -1
- package/app/scripts/helpers/dropdown.helper.js +9 -0
- package/app/styles/_buttons.scss +4 -1
- package/app/styles/_helpers.scss +25 -6
- package/app/styles/_popover.scss +8 -8
- package/app/styles/_tooltips.scss +83 -0
- package/app/styles/design-tokens/_design-tokens-general.scss +6 -0
- package/app/styles/form-elements/_checkbox.scss +9 -5
- package/app/styles/form-elements/_inputs.scss +7 -1
- package/app-typescript/components/Autocomplete.tsx +1 -1
- package/app-typescript/components/Form/InputWrapper.tsx +1 -1
- package/app-typescript/components/Popover.tsx +2 -0
- package/app-typescript/components/SelectGrid.tsx +3 -1
- package/app-typescript/components/TimePicker/TimePickerPopover.spec.ts +163 -0
- package/app-typescript/components/TimePicker/TimePickerPopover.tsx +286 -0
- package/app-typescript/components/TimePicker/TimeValueHolder.tsx +36 -0
- package/app-typescript/components/{TimePicker.tsx → TimePicker/index.tsx} +6 -12
- package/app-typescript/components/Tooltip.tsx +1 -1
- package/app-typescript/components/TooltipV2.tsx +10 -21
- package/app-typescript/components/_Positioner.tsx +2 -0
- package/dist/components/Popover.tsx +31 -8
- package/dist/components/TimePicker.tsx +7 -2
- package/dist/components/Tooltips.tsx +15 -13
- package/dist/components/utilities/SpacingUtilities.tsx +126 -126
- package/dist/components/utilities/TextUtilities.tsx +51 -37
- package/dist/examples.bundle.js +1354 -1199
- package/dist/superdesk-ui.bundle.css +146 -41
- package/dist/superdesk-ui.bundle.js +829 -741
- package/dist/vendor.bundle.js +15 -15
- package/package.json +1 -1
- package/react/components/Autocomplete.js +2 -1
- package/react/components/Form/InputWrapper.js +2 -1
- package/react/components/Popover.d.ts +1 -0
- package/react/components/Popover.js +1 -1
- package/react/components/SelectGrid.js +2 -1
- package/react/components/TimePicker/TimePickerPopover.d.ts +27 -0
- package/react/components/TimePicker/TimePickerPopover.js +231 -0
- package/react/components/TimePicker/TimeValueHolder.d.ts +13 -0
- package/react/components/TimePicker/TimeValueHolder.js +73 -0
- package/react/components/{TimePicker.d.ts → TimePicker/index.d.ts} +1 -1
- package/react/components/{TimePicker.js → TimePicker/index.js} +5 -9
- package/react/components/Tooltip.js +1 -1
- package/react/components/TooltipV2.js +10 -18
- package/react/components/_Positioner.d.ts +1 -0
- package/react/components/_Positioner.js +1 -1
- package/app-typescript/components/TimePickerPopover.tsx +0 -283
- package/react/components/TimePickerPopover.d.ts +0 -18
- package/react/components/TimePickerPopover.js +0 -222
package/.mocharc.json
CHANGED
|
@@ -192,6 +192,15 @@ angular.module('superdesk-ui.helper.dropdown', ['superdesk-ui.helper.position'])
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
$animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass).then(() => {
|
|
195
|
+
// NOTE: this checks whether there is at least one dropdown open - not only this instance
|
|
196
|
+
const legacyAngularDropdownOpen = document.querySelector('.dropdown.open') != null;
|
|
197
|
+
|
|
198
|
+
if (legacyAngularDropdownOpen) {
|
|
199
|
+
document.body.classList.add('legacyAngularDropdownOpen');
|
|
200
|
+
} else {
|
|
201
|
+
document.body.classList.remove('legacyAngularDropdownOpen');
|
|
202
|
+
}
|
|
203
|
+
|
|
195
204
|
if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
|
|
196
205
|
toggleInvoker($scope, {open: !!isOpen});
|
|
197
206
|
}
|
package/app/styles/_buttons.scss
CHANGED
|
@@ -372,6 +372,7 @@ $icn-button-focus-box-shadow: 0 0 0 2px $sd-colour--focus-shadow;
|
|
|
372
372
|
[class^="icon-"], [class*=" icon-"] {
|
|
373
373
|
color: var(--color-icon-default) !important;
|
|
374
374
|
vertical-align: baseline !important;
|
|
375
|
+
pointer-events: none;
|
|
375
376
|
}
|
|
376
377
|
|
|
377
378
|
&:hover {
|
|
@@ -401,8 +402,10 @@ $icn-button-focus-box-shadow: 0 0 0 2px $sd-colour--focus-shadow;
|
|
|
401
402
|
}
|
|
402
403
|
}
|
|
403
404
|
|
|
404
|
-
&--disabled
|
|
405
|
+
&--disabled,
|
|
406
|
+
&:disabled {
|
|
405
407
|
opacity: $icn-button-opacity-disabled;
|
|
408
|
+
pointer-events: none;
|
|
406
409
|
|
|
407
410
|
&:hover, &:active, &:focus-visible {
|
|
408
411
|
background-color: transparent !important;
|
package/app/styles/_helpers.scss
CHANGED
|
@@ -1866,21 +1866,22 @@ h6 {
|
|
|
1866
1866
|
|
|
1867
1867
|
// LINE HIGHT
|
|
1868
1868
|
.line-height-1 {
|
|
1869
|
-
line-height:
|
|
1869
|
+
line-height: var(--l-height-none);
|
|
1870
1870
|
}
|
|
1871
1871
|
.line-height-xs {
|
|
1872
|
-
line-height:
|
|
1872
|
+
line-height: var(--l-height-xs);
|
|
1873
1873
|
}
|
|
1874
1874
|
.line-height-sm {
|
|
1875
|
-
line-height:
|
|
1875
|
+
line-height: var(--l-height-sm);
|
|
1876
1876
|
}
|
|
1877
1877
|
.line-height-md {
|
|
1878
|
-
line-height:
|
|
1878
|
+
line-height: var(--l-height-md);
|
|
1879
1879
|
}
|
|
1880
1880
|
.line-height-lg {
|
|
1881
|
-
line-height:
|
|
1881
|
+
line-height: var(--l-height-lg);
|
|
1882
1882
|
}
|
|
1883
1883
|
|
|
1884
|
+
|
|
1884
1885
|
// LINE CLAMP
|
|
1885
1886
|
// limit the number of horizontal lines in an elemnt (e.g. <p>)
|
|
1886
1887
|
// it doesn't work if the element has set flex-grow: 1;
|
|
@@ -2204,6 +2205,8 @@ h6 {
|
|
|
2204
2205
|
container-type: inline-size;
|
|
2205
2206
|
container-name: left-panel;
|
|
2206
2207
|
}
|
|
2208
|
+
|
|
2209
|
+
|
|
2207
2210
|
.new-form-layout {
|
|
2208
2211
|
--form-group-gap: var(--gap-5);
|
|
2209
2212
|
--form-layout-gap: var(--gap-4);
|
|
@@ -2216,22 +2219,38 @@ h6 {
|
|
|
2216
2219
|
background-color: var(--color-surface-base);
|
|
2217
2220
|
border-radius: var(--b-radius--large);
|
|
2218
2221
|
border: 1px solid var(--color-line-light);
|
|
2219
|
-
|
|
2220
2222
|
.new-form-heading {
|
|
2221
2223
|
font-family: $baseFontFamilySerif;
|
|
2222
2224
|
font-weight: 900;
|
|
2223
2225
|
font-size: var(--form-heading-font-size);
|
|
2224
2226
|
line-height: 1.2;
|
|
2225
2227
|
}
|
|
2228
|
+
legend {
|
|
2229
|
+
float: left;
|
|
2230
|
+
}
|
|
2226
2231
|
}
|
|
2227
2232
|
.new-form-group {
|
|
2228
2233
|
display: flex;
|
|
2229
2234
|
gap: var(--form-group-gap);
|
|
2235
|
+
&.new-form-group--grid {
|
|
2236
|
+
display: grid;
|
|
2237
|
+
grid-template-columns: repeat(4, 1fr);
|
|
2238
|
+
gap: var(--form-group-gap);
|
|
2239
|
+
}
|
|
2230
2240
|
}
|
|
2231
2241
|
.new-form-group-item {
|
|
2232
2242
|
display: flex;
|
|
2233
2243
|
flex-direction: column;
|
|
2234
2244
|
flex-grow: 1;
|
|
2245
|
+
&.new-form-group-item--span-2 {
|
|
2246
|
+
grid-column: span 2;
|
|
2247
|
+
}
|
|
2248
|
+
&.new-form-group-item--span-3 {
|
|
2249
|
+
grid-column: span 3;
|
|
2250
|
+
}
|
|
2251
|
+
&.new-form-group-item--span-4 {
|
|
2252
|
+
grid-column: span 4;
|
|
2253
|
+
}
|
|
2235
2254
|
}
|
|
2236
2255
|
|
|
2237
2256
|
@container left-panel (width <= 900px) {
|
package/app/styles/_popover.scss
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
.sd-popover {
|
|
2
|
-
background: var(--
|
|
3
|
-
color:
|
|
4
|
-
padding:
|
|
5
|
-
border-radius:
|
|
6
|
-
box-shadow:
|
|
2
|
+
background: var(--color-surface-base);
|
|
3
|
+
color: var(--color-text-default);
|
|
4
|
+
padding: var(--space--1) var(--space--1-5) var(--space--1-5);
|
|
5
|
+
border-radius: var(--b-radius--medium);
|
|
6
|
+
box-shadow: var(--sd-shadow--z4);
|
|
7
7
|
max-width: 320px !important;
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
display: flex;
|
|
12
12
|
justify-content: space-between;
|
|
13
13
|
align-items: center;
|
|
14
|
-
margin-block-end:
|
|
14
|
+
margin-block-end: var(--space--0-5);
|
|
15
15
|
min-height: 20px;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
.sd-popover__title {
|
|
19
|
-
font-size:
|
|
19
|
+
font-size: var(--text-size-xx-small);
|
|
20
20
|
line-height: 1;
|
|
21
21
|
text-transform: uppercase;
|
|
22
|
-
color:
|
|
22
|
+
color: var(--color-text-muted);
|
|
23
23
|
padding: 0;
|
|
24
24
|
margin: 0;
|
|
25
25
|
}
|
|
@@ -340,3 +340,86 @@
|
|
|
340
340
|
.p-tooltip-right {
|
|
341
341
|
margin-inline-start: 8px;
|
|
342
342
|
}
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
// NEW TOOLTIP STYLES ----------------------------------------------------------------------------
|
|
348
|
+
|
|
349
|
+
.tooltip {
|
|
350
|
+
--tooltip-arrow_border: 6px;
|
|
351
|
+
margin: calc(var(--tooltip-arrow_border) / 2);
|
|
352
|
+
border-radius: var(--b-radius--medium);
|
|
353
|
+
padding: var(--space--1) var(--space--1-5);
|
|
354
|
+
font-size: var(--text-size-small);
|
|
355
|
+
position: relative;
|
|
356
|
+
background-color: var(--sd-colour-background__tooltip);
|
|
357
|
+
box-shadow: var(--sd-shadow--z3);
|
|
358
|
+
color: var(--color-text-ondark);
|
|
359
|
+
opacity: 1;
|
|
360
|
+
transition: opacity 400ms ease-out, margin 200ms ease-out;
|
|
361
|
+
transition-behavior: allow-discrete;
|
|
362
|
+
|
|
363
|
+
@starting-style {
|
|
364
|
+
opacity: 0;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
&::before {
|
|
368
|
+
content: '';
|
|
369
|
+
border: var(--tooltip-arrow_border) solid transparent;
|
|
370
|
+
border-width: var(--tooltip-arrow_border);
|
|
371
|
+
z-index: 1001;
|
|
372
|
+
user-select: none;
|
|
373
|
+
pointer-events: none;
|
|
374
|
+
position: absolute;
|
|
375
|
+
overflow: hidden;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
[data-popper-placement^="top"] {
|
|
380
|
+
.tooltip {
|
|
381
|
+
margin-block-end: var(--tooltip-arrow_border);
|
|
382
|
+
&::before {
|
|
383
|
+
inset-block-end: calc(var(--tooltip-arrow_border) * -1);
|
|
384
|
+
inset-inline-start: calc(50% - var(--tooltip-arrow_border));
|
|
385
|
+
border-bottom-width: 0;
|
|
386
|
+
border-top-color: var(--sd-colour-background__tooltip);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
[data-popper-placement^="bottom"] {
|
|
392
|
+
.tooltip {
|
|
393
|
+
margin-block-start: var(--tooltip-arrow_border);
|
|
394
|
+
&::before {
|
|
395
|
+
inset-block-start: calc(var(--tooltip-arrow_border) * -1);
|
|
396
|
+
inset-inline-start: calc(50% - var(--tooltip-arrow_border));
|
|
397
|
+
border-top-width: 0;
|
|
398
|
+
border-bottom-color: var(--sd-colour-background__tooltip);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
[data-popper-placement^="left"] {
|
|
404
|
+
.tooltip {
|
|
405
|
+
margin-inline-end: var(--tooltip-arrow_border);
|
|
406
|
+
&::before {
|
|
407
|
+
inset-inline-end: calc(var(--tooltip-arrow_border) * -1);
|
|
408
|
+
inset-block-start: calc(50% - var(--tooltip-arrow_border));
|
|
409
|
+
border-right-width: 0;
|
|
410
|
+
border-left-color: var(--sd-colour-background__tooltip);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
[data-popper-placement^="right"] {
|
|
416
|
+
.tooltip {
|
|
417
|
+
margin-inline-start: var(--tooltip-arrow_border);
|
|
418
|
+
&::before {
|
|
419
|
+
inset-inline-start: calc(var(--tooltip-arrow_border) * -1);
|
|
420
|
+
inset-block-start: calc(50% - var(--tooltip-arrow_border));
|
|
421
|
+
border-left-width: 0;
|
|
422
|
+
border-right-color: var(--sd-colour-background__tooltip);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
@@ -70,6 +70,12 @@
|
|
|
70
70
|
--text-size-x-large: calc(var(--text-size--base) * 2.4); // 24px;
|
|
71
71
|
--text-size-xx-large: calc(var(--text-size--base) * 3.2); // 32px;
|
|
72
72
|
|
|
73
|
+
// LINE HEIGHT
|
|
74
|
+
--l-height-none: 1;
|
|
75
|
+
--l-height-xs: 1.1;
|
|
76
|
+
--l-height-sm: 1.2;
|
|
77
|
+
--l-height-md: 1.4;
|
|
78
|
+
--l-height-lg: 1.5;
|
|
73
79
|
|
|
74
80
|
// SHADOW
|
|
75
81
|
--sd-shadow--z1: 0 0 0 1px var(--sd-shadow-outline), 0 1px 3px hsla(0, 0%, 0%, 0.16), 0 0 1px hsla(0, 0%, 0%, 0.1);
|
|
@@ -8,8 +8,9 @@ $checkButtonBorderColorHover: var(--sd-colour-line--strong);
|
|
|
8
8
|
$checkButtonBorderRadius: $border-radius__base--small;
|
|
9
9
|
|
|
10
10
|
@mixin check-base {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
--check-size: 1.6rem;
|
|
12
|
+
width: var(--check-size);
|
|
13
|
+
height: var(--check-size);
|
|
13
14
|
display: inline-block;
|
|
14
15
|
position: relative;
|
|
15
16
|
background: transparent;
|
|
@@ -17,6 +18,7 @@ $checkButtonBorderRadius: $border-radius__base--small;
|
|
|
17
18
|
vertical-align: middle;
|
|
18
19
|
font-family: $baseFontFamily;
|
|
19
20
|
transition: all 0.2s ease-out;
|
|
21
|
+
flex: 0 0 var(--check-size);
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
.sd-checkbox {
|
|
@@ -132,7 +134,8 @@ $checkButtonBorderRadius: $border-radius__base--small;
|
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
i + label {
|
|
135
|
-
margin-inline-start:
|
|
137
|
+
margin-inline-start: var(--space--1);
|
|
138
|
+
font-size: var(--text-size-small);
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
&::after {
|
|
@@ -383,7 +386,7 @@ $checkButtonBorderRadius: $border-radius__base--small;
|
|
|
383
386
|
}
|
|
384
387
|
|
|
385
388
|
i + .sd-check-button__text-label {
|
|
386
|
-
margin-inline-start:
|
|
389
|
+
margin-inline-start: var(--space--1);
|
|
387
390
|
}
|
|
388
391
|
|
|
389
392
|
&:hover {
|
|
@@ -501,7 +504,8 @@ $checkButtonBorderRadius: $border-radius__base--small;
|
|
|
501
504
|
|
|
502
505
|
.sd-check-new + label,
|
|
503
506
|
.sd-radio-new + label {
|
|
504
|
-
margin-inline-start:
|
|
507
|
+
margin-inline-start: var(--space--1);
|
|
508
|
+
font-size: var(--text-size-small);
|
|
505
509
|
}
|
|
506
510
|
|
|
507
511
|
.sd-check-new + label:empty,
|
|
@@ -781,7 +781,7 @@ input[type="color" i].sd-input__color-input::-webkit-color-swatch {
|
|
|
781
781
|
margin: 0;
|
|
782
782
|
display: grid;
|
|
783
783
|
grid-template-columns: auto 1fr auto;
|
|
784
|
-
grid-template-rows: $form-label-height auto
|
|
784
|
+
grid-template-rows: $form-label-height auto 1fr;
|
|
785
785
|
grid-gap: 0;
|
|
786
786
|
position: relative;
|
|
787
787
|
align-self: stretch;
|
|
@@ -940,6 +940,12 @@ input[type="color" i].sd-input__color-input::-webkit-color-swatch {
|
|
|
940
940
|
margin: 0;
|
|
941
941
|
grid-row: 1/2;
|
|
942
942
|
grid-column: 2/4;
|
|
943
|
+
span {
|
|
944
|
+
overflow: hidden;
|
|
945
|
+
text-overflow: ellipsis;
|
|
946
|
+
white-space: nowrap;
|
|
947
|
+
max-width: 100%;
|
|
948
|
+
}
|
|
943
949
|
}
|
|
944
950
|
|
|
945
951
|
.sd-input__label--required::after {
|
|
@@ -126,7 +126,7 @@ export class Autocomplete extends React.Component<IProps, IState> {
|
|
|
126
126
|
<div className={classes}>
|
|
127
127
|
{this.props.label && !this.props.isSearchField ? (
|
|
128
128
|
<label className="sd-input__label" htmlFor={this.htmlId}>
|
|
129
|
-
{this.props.label}
|
|
129
|
+
<span>{this.props.label}</span>
|
|
130
130
|
</label>
|
|
131
131
|
) : null}
|
|
132
132
|
|
|
@@ -95,7 +95,7 @@ export class InputWrapper extends React.Component<IProps, IState> {
|
|
|
95
95
|
id={this.props.htmlId + 'label'}
|
|
96
96
|
tabIndex={this.props.tabindex === undefined ? undefined : -1}
|
|
97
97
|
>
|
|
98
|
-
{this.props.label}
|
|
98
|
+
<span>{this.props.label}</span>
|
|
99
99
|
</label>
|
|
100
100
|
<div className="sd-input__input-container">{this.props.children}</div>
|
|
101
101
|
{this.props.maxLength && (
|
|
@@ -7,6 +7,7 @@ interface IProps {
|
|
|
7
7
|
triggerSelector: string; // CSS selector for an element that will be used to toggle the popover.
|
|
8
8
|
displayCloseButton?: boolean; // defaults to true
|
|
9
9
|
placement?: PopperOptions['placement']; // defaults to auto
|
|
10
|
+
theme?: 'light-ui' | 'dark-ui';
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export class Popover extends React.Component<IProps> {
|
|
@@ -14,6 +15,7 @@ export class Popover extends React.Component<IProps> {
|
|
|
14
15
|
return (
|
|
15
16
|
<Positioner
|
|
16
17
|
triggerSelector={this.props.triggerSelector}
|
|
18
|
+
theme={this.props.theme}
|
|
17
19
|
placement={this.props.placement ?? 'auto'}
|
|
18
20
|
className="sd-popover"
|
|
19
21
|
>
|
|
@@ -171,7 +171,9 @@ export class SelectGrid extends React.PureComponent<IProps, IState> {
|
|
|
171
171
|
aria-label={this.props.label}
|
|
172
172
|
key={this.props.label}
|
|
173
173
|
>
|
|
174
|
-
<label className="sd-input__label">
|
|
174
|
+
<label className="sd-input__label">
|
|
175
|
+
<span>{this.props.label}</span>
|
|
176
|
+
</label>
|
|
175
177
|
<TriggerTemplate onClick={this.mountPopup} />
|
|
176
178
|
</div>
|
|
177
179
|
<OverlayPanel
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import {describe, it} from 'mocha';
|
|
2
|
+
import * as assert from 'assert';
|
|
3
|
+
import {convert12HourTo24Hour, convert24HourTo12Hour, toInternalState} from './TimePickerPopover';
|
|
4
|
+
|
|
5
|
+
it('should convert all 12-hour times to 24-hour format', () => {
|
|
6
|
+
// AM times
|
|
7
|
+
assert.strictEqual(convert12HourTo24Hour(12, 'am'), 0);
|
|
8
|
+
assert.strictEqual(convert12HourTo24Hour(1, 'am'), 1);
|
|
9
|
+
assert.strictEqual(convert12HourTo24Hour(2, 'am'), 2);
|
|
10
|
+
assert.strictEqual(convert12HourTo24Hour(3, 'am'), 3);
|
|
11
|
+
assert.strictEqual(convert12HourTo24Hour(4, 'am'), 4);
|
|
12
|
+
assert.strictEqual(convert12HourTo24Hour(5, 'am'), 5);
|
|
13
|
+
assert.strictEqual(convert12HourTo24Hour(6, 'am'), 6);
|
|
14
|
+
assert.strictEqual(convert12HourTo24Hour(7, 'am'), 7);
|
|
15
|
+
assert.strictEqual(convert12HourTo24Hour(8, 'am'), 8);
|
|
16
|
+
assert.strictEqual(convert12HourTo24Hour(9, 'am'), 9);
|
|
17
|
+
assert.strictEqual(convert12HourTo24Hour(10, 'am'), 10);
|
|
18
|
+
assert.strictEqual(convert12HourTo24Hour(11, 'am'), 11);
|
|
19
|
+
|
|
20
|
+
// PM times
|
|
21
|
+
assert.strictEqual(convert12HourTo24Hour(12, 'pm'), 12);
|
|
22
|
+
assert.strictEqual(convert12HourTo24Hour(1, 'pm'), 13);
|
|
23
|
+
assert.strictEqual(convert12HourTo24Hour(2, 'pm'), 14);
|
|
24
|
+
assert.strictEqual(convert12HourTo24Hour(3, 'pm'), 15);
|
|
25
|
+
assert.strictEqual(convert12HourTo24Hour(4, 'pm'), 16);
|
|
26
|
+
assert.strictEqual(convert12HourTo24Hour(5, 'pm'), 17);
|
|
27
|
+
assert.strictEqual(convert12HourTo24Hour(6, 'pm'), 18);
|
|
28
|
+
assert.strictEqual(convert12HourTo24Hour(7, 'pm'), 19);
|
|
29
|
+
assert.strictEqual(convert12HourTo24Hour(8, 'pm'), 20);
|
|
30
|
+
assert.strictEqual(convert12HourTo24Hour(9, 'pm'), 21);
|
|
31
|
+
assert.strictEqual(convert12HourTo24Hour(10, 'pm'), 22);
|
|
32
|
+
assert.strictEqual(convert12HourTo24Hour(11, 'pm'), 23);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should convert all 24-hour times to 12-hour format', () => {
|
|
36
|
+
assert.strictEqual(convert24HourTo12Hour(0), 12);
|
|
37
|
+
assert.strictEqual(convert24HourTo12Hour(1), 1);
|
|
38
|
+
assert.strictEqual(convert24HourTo12Hour(2), 2);
|
|
39
|
+
assert.strictEqual(convert24HourTo12Hour(3), 3);
|
|
40
|
+
assert.strictEqual(convert24HourTo12Hour(4), 4);
|
|
41
|
+
assert.strictEqual(convert24HourTo12Hour(5), 5);
|
|
42
|
+
assert.strictEqual(convert24HourTo12Hour(6), 6);
|
|
43
|
+
assert.strictEqual(convert24HourTo12Hour(7), 7);
|
|
44
|
+
assert.strictEqual(convert24HourTo12Hour(8), 8);
|
|
45
|
+
assert.strictEqual(convert24HourTo12Hour(9), 9);
|
|
46
|
+
assert.strictEqual(convert24HourTo12Hour(10), 10);
|
|
47
|
+
assert.strictEqual(convert24HourTo12Hour(11), 11);
|
|
48
|
+
assert.strictEqual(convert24HourTo12Hour(12), 12);
|
|
49
|
+
assert.strictEqual(convert24HourTo12Hour(13), 1);
|
|
50
|
+
assert.strictEqual(convert24HourTo12Hour(14), 2);
|
|
51
|
+
assert.strictEqual(convert24HourTo12Hour(15), 3);
|
|
52
|
+
assert.strictEqual(convert24HourTo12Hour(16), 4);
|
|
53
|
+
assert.strictEqual(convert24HourTo12Hour(17), 5);
|
|
54
|
+
assert.strictEqual(convert24HourTo12Hour(18), 6);
|
|
55
|
+
assert.strictEqual(convert24HourTo12Hour(19), 7);
|
|
56
|
+
assert.strictEqual(convert24HourTo12Hour(20), 8);
|
|
57
|
+
assert.strictEqual(convert24HourTo12Hour(21), 9);
|
|
58
|
+
assert.strictEqual(convert24HourTo12Hour(22), 10);
|
|
59
|
+
assert.strictEqual(convert24HourTo12Hour(23), 11);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe('toInternalState', () => {
|
|
63
|
+
describe('null/undefined/empty input', () => {
|
|
64
|
+
it('should return null state for null input', () => {
|
|
65
|
+
assert.deepStrictEqual(toInternalState(null), {
|
|
66
|
+
hours: null,
|
|
67
|
+
minutes: null,
|
|
68
|
+
seconds: null,
|
|
69
|
+
period: null,
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('should return null state for undefined input', () => {
|
|
74
|
+
assert.deepStrictEqual(toInternalState(undefined), {
|
|
75
|
+
hours: null,
|
|
76
|
+
minutes: null,
|
|
77
|
+
seconds: null,
|
|
78
|
+
period: null,
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should return null state for empty string', () => {
|
|
83
|
+
assert.deepStrictEqual(toInternalState(' '), {
|
|
84
|
+
hours: null,
|
|
85
|
+
minutes: null,
|
|
86
|
+
seconds: null,
|
|
87
|
+
period: null,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should convert 00:00:00 to 12:00:00 am', () => {
|
|
93
|
+
assert.deepStrictEqual(toInternalState('00:00:00'), {
|
|
94
|
+
hours: '12',
|
|
95
|
+
minutes: '00',
|
|
96
|
+
seconds: '00',
|
|
97
|
+
period: 'am',
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should convert 01:30:45 to 01:30:45 am', () => {
|
|
102
|
+
assert.deepStrictEqual(toInternalState('01:30:45'), {
|
|
103
|
+
hours: '01',
|
|
104
|
+
minutes: '30',
|
|
105
|
+
seconds: '45',
|
|
106
|
+
period: 'am',
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should convert 11:59:59 to 11:59:59 am', () => {
|
|
111
|
+
assert.deepStrictEqual(toInternalState('11:59:59'), {
|
|
112
|
+
hours: '11',
|
|
113
|
+
minutes: '59',
|
|
114
|
+
seconds: '59',
|
|
115
|
+
period: 'am',
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should convert 12:00:00 to 12:00:00 pm', () => {
|
|
120
|
+
assert.deepStrictEqual(toInternalState('12:00:00'), {
|
|
121
|
+
hours: '12',
|
|
122
|
+
minutes: '00',
|
|
123
|
+
seconds: '00',
|
|
124
|
+
period: 'pm',
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should convert 13:30:15 to 01:30:15 pm', () => {
|
|
129
|
+
assert.deepStrictEqual(toInternalState('13:30:15'), {
|
|
130
|
+
hours: '01',
|
|
131
|
+
minutes: '30',
|
|
132
|
+
seconds: '15',
|
|
133
|
+
period: 'pm',
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should convert 23:59:59 to 11:59:59 pm', () => {
|
|
138
|
+
assert.deepStrictEqual(toInternalState('23:59:59'), {
|
|
139
|
+
hours: '11',
|
|
140
|
+
minutes: '59',
|
|
141
|
+
seconds: '59',
|
|
142
|
+
period: 'pm',
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should handle time without seconds and default to 00', () => {
|
|
147
|
+
assert.deepStrictEqual(toInternalState('14:30'), {
|
|
148
|
+
hours: '02',
|
|
149
|
+
minutes: '30',
|
|
150
|
+
seconds: '00',
|
|
151
|
+
period: 'pm',
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should handle time without seconds in morning', () => {
|
|
156
|
+
assert.deepStrictEqual(toInternalState('09:15'), {
|
|
157
|
+
hours: '09',
|
|
158
|
+
minutes: '15',
|
|
159
|
+
seconds: '00',
|
|
160
|
+
period: 'am',
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|