@aquera/nile-elements 1.8.1 → 1.8.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.
- package/README.md +6 -0
- package/dist/index.js +370 -177
- package/dist/nile-detail/nile-detail.cjs.js +1 -1
- package/dist/nile-detail/nile-detail.cjs.js.map +1 -1
- package/dist/nile-detail/nile-detail.css.cjs.js +1 -1
- package/dist/nile-detail/nile-detail.css.cjs.js.map +1 -1
- package/dist/nile-detail/nile-detail.css.esm.js +37 -1
- package/dist/nile-detail/nile-detail.esm.js +17 -9
- package/dist/nile-detail/nile-detail.utils.cjs.js +1 -1
- package/dist/nile-detail/nile-detail.utils.cjs.js.map +1 -1
- package/dist/nile-detail/nile-detail.utils.esm.js +1 -1
- package/dist/nile-slider/nile-slider.cjs.js +1 -1
- package/dist/nile-slider/nile-slider.cjs.js.map +1 -1
- package/dist/nile-slider/nile-slider.css.cjs.js +1 -1
- package/dist/nile-slider/nile-slider.css.cjs.js.map +1 -1
- package/dist/nile-slider/nile-slider.css.esm.js +162 -41
- package/dist/nile-slider/nile-slider.esm.js +5 -3
- package/dist/nile-slider/nile-slider.template.cjs.js +1 -1
- package/dist/nile-slider/nile-slider.template.cjs.js.map +1 -1
- package/dist/nile-slider/nile-slider.template.esm.js +49 -23
- package/dist/nile-slider/utils/nile-slider.utils.cjs.js +1 -1
- package/dist/nile-slider/utils/nile-slider.utils.cjs.js.map +1 -1
- package/dist/nile-slider/utils/nile-slider.utils.esm.js +1 -1
- package/dist/src/nile-detail/nile-detail.css.js +37 -1
- package/dist/src/nile-detail/nile-detail.css.js.map +1 -1
- package/dist/src/nile-detail/nile-detail.d.ts +15 -0
- package/dist/src/nile-detail/nile-detail.js +85 -4
- package/dist/src/nile-detail/nile-detail.js.map +1 -1
- package/dist/src/nile-detail/nile-detail.utils.d.ts +1 -0
- package/dist/src/nile-detail/nile-detail.utils.js +34 -4
- package/dist/src/nile-detail/nile-detail.utils.js.map +1 -1
- package/dist/src/nile-slider/nile-slider.css.js +160 -39
- package/dist/src/nile-slider/nile-slider.css.js.map +1 -1
- package/dist/src/nile-slider/nile-slider.d.ts +5 -1
- package/dist/src/nile-slider/nile-slider.js +23 -1
- package/dist/src/nile-slider/nile-slider.js.map +1 -1
- package/dist/src/nile-slider/nile-slider.template.d.ts +2 -0
- package/dist/src/nile-slider/nile-slider.template.js +38 -1
- package/dist/src/nile-slider/nile-slider.template.js.map +1 -1
- package/dist/src/nile-slider/types/nile-slider.types.d.ts +1 -0
- package/dist/src/nile-slider/types/nile-slider.types.js.map +1 -1
- package/dist/src/nile-slider/utils/nile-slider.utils.js +4 -0
- package/dist/src/nile-slider/utils/nile-slider.utils.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/nile-detail/nile-detail.css.ts +37 -1
- package/src/nile-detail/nile-detail.ts +87 -3
- package/src/nile-detail/nile-detail.utils.ts +34 -4
- package/src/nile-slider/nile-slider.css.ts +160 -39
- package/src/nile-slider/nile-slider.template.ts +45 -2
- package/src/nile-slider/nile-slider.ts +11 -3
- package/src/nile-slider/types/nile-slider.types.ts +2 -0
- package/src/nile-slider/utils/nile-slider.utils.ts +2 -0
- package/vscode-html-custom-data.json +48 -10
package/package.json
CHANGED
|
@@ -154,6 +154,41 @@ export const styles = css`
|
|
|
154
154
|
padding: 0;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/* ── Preview state ──────────────────────────────────────────────────────── */
|
|
158
|
+
|
|
159
|
+
.detail__body--preview {
|
|
160
|
+
position: relative;
|
|
161
|
+
cursor: pointer;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.detail__body--preview::after {
|
|
165
|
+
content: '';
|
|
166
|
+
position: absolute;
|
|
167
|
+
left: 0;
|
|
168
|
+
right: 0;
|
|
169
|
+
bottom: 0;
|
|
170
|
+
height: var(--nile-detail-preview-fade-height, 40px);
|
|
171
|
+
background: linear-gradient(
|
|
172
|
+
to bottom,
|
|
173
|
+
transparent,
|
|
174
|
+
var(--nile-colors-white-base, var(--ng-colors-bg-primary))
|
|
175
|
+
);
|
|
176
|
+
pointer-events: none;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.detail__body--preview:focus {
|
|
180
|
+
outline: none;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.detail__body--preview:focus-visible {
|
|
184
|
+
outline: solid 3px var(--nile-colors-blue-500, var(--ng-colors-fg-brand-primary-600));
|
|
185
|
+
outline-offset: -3px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.detail--disabled .detail__body--preview {
|
|
189
|
+
cursor: not-allowed;
|
|
190
|
+
}
|
|
191
|
+
|
|
157
192
|
/* ── Selection variant ──────────────────────────────────────────────────── */
|
|
158
193
|
|
|
159
194
|
.detail__selection-label {
|
|
@@ -410,7 +445,8 @@ export const styles = css`
|
|
|
410
445
|
var(--nile-spacing-3xl, var(--ng-spacing-3xl));
|
|
411
446
|
}
|
|
412
447
|
|
|
413
|
-
.detail--light.detail--open .detail__header
|
|
448
|
+
.detail--light.detail--open .detail__header,
|
|
449
|
+
.detail--light.detail--preview .detail__header {
|
|
414
450
|
border-bottom: 1px solid var(--nile-colors-neutral-400, var(--ng-colors-border-secondary));
|
|
415
451
|
}
|
|
416
452
|
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
hideDetail,
|
|
13
13
|
handleSummaryClick,
|
|
14
14
|
handleSummaryKeyDown,
|
|
15
|
+
getPreviewHeight,
|
|
15
16
|
} from './nile-detail.utils';
|
|
16
17
|
import '../nile-checkbox/index';
|
|
17
18
|
import '../nile-input/index';
|
|
@@ -104,6 +105,10 @@ export interface NileDetailSelectionConfig {
|
|
|
104
105
|
|
|
105
106
|
showSelectedToggle?: boolean;
|
|
106
107
|
|
|
108
|
+
// Preview state
|
|
109
|
+
preview?: boolean;
|
|
110
|
+
previewPercentage?: number;
|
|
111
|
+
|
|
107
112
|
// Inherited / passthrough
|
|
108
113
|
open?: boolean;
|
|
109
114
|
disabled?: boolean;
|
|
@@ -128,6 +133,12 @@ export class NileDetail extends NileElement {
|
|
|
128
133
|
|
|
129
134
|
@property({ attribute: true, type: Boolean, reflect: true }) disabled = false;
|
|
130
135
|
|
|
136
|
+
/** When set, the closed state shows a preview of the body content instead of hiding it. */
|
|
137
|
+
@property({ attribute: true, type: Boolean, reflect: true }) preview = false;
|
|
138
|
+
|
|
139
|
+
/** Percentage (0–100) of the content height shown while previewing. */
|
|
140
|
+
@property({ attribute: 'preview-percentage', type: Number, reflect: true }) previewPercentage = 30;
|
|
141
|
+
|
|
131
142
|
@property({ attribute: true, type: String, reflect: true }) variant: NileDetailVariant = 'default';
|
|
132
143
|
|
|
133
144
|
@property({ attribute: false, type: Array }) items: SelectionItem[] = [];
|
|
@@ -218,6 +229,16 @@ export class NileDetail extends NileElement {
|
|
|
218
229
|
return this.variant === 'light' || this.variant === 'select-light';
|
|
219
230
|
}
|
|
220
231
|
|
|
232
|
+
/** True when preview mode is on with a usable percentage. */
|
|
233
|
+
private get _previewEnabled(): boolean {
|
|
234
|
+
return this.preview && Math.min(100, Math.max(0, this.previewPercentage)) > 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** True when the closed state should currently render the preview. */
|
|
238
|
+
private get _isPreviewActive(): boolean {
|
|
239
|
+
return this._previewEnabled && !this.open;
|
|
240
|
+
}
|
|
241
|
+
|
|
221
242
|
private get _isInfiniteMode(): boolean {
|
|
222
243
|
return (
|
|
223
244
|
this._isSelectionVariant &&
|
|
@@ -308,9 +329,12 @@ export class NileDetail extends NileElement {
|
|
|
308
329
|
}
|
|
309
330
|
|
|
310
331
|
firstUpdated() {
|
|
311
|
-
this._detailOpen = this.open;
|
|
312
|
-
this.body.hidden = !this.open;
|
|
332
|
+
this._detailOpen = this.open || this._isPreviewActive;
|
|
333
|
+
this.body.hidden = !this.open && !this._isPreviewActive;
|
|
313
334
|
this.body.style.height = this.open ? 'auto' : '0';
|
|
335
|
+
if (this._isPreviewActive) {
|
|
336
|
+
this._applyPreviewHeight();
|
|
337
|
+
}
|
|
314
338
|
this._syncSelectedFromProperty();
|
|
315
339
|
if (this._restoreDefaults === null) {
|
|
316
340
|
this._restoreDefaults = [...this._selectedSet];
|
|
@@ -541,6 +565,9 @@ export class NileDetail extends NileElement {
|
|
|
541
565
|
}
|
|
542
566
|
|
|
543
567
|
if (c.showSelectedToggle !== undefined) this.showSelectedToggle = c.showSelectedToggle;
|
|
568
|
+
|
|
569
|
+
if (c.preview !== undefined) this.preview = c.preview;
|
|
570
|
+
if (c.previewPercentage !== undefined) this.previewPercentage = c.previewPercentage;
|
|
544
571
|
}
|
|
545
572
|
|
|
546
573
|
private _syncSelectedFromProperty() {
|
|
@@ -728,6 +755,9 @@ export class NileDetail extends NileElement {
|
|
|
728
755
|
if (node.nodeType === Node.TEXT_NODE) return !!(node.textContent && node.textContent.trim());
|
|
729
756
|
return false;
|
|
730
757
|
});
|
|
758
|
+
if (this._isPreviewActive) {
|
|
759
|
+
this._applyPreviewHeight();
|
|
760
|
+
}
|
|
731
761
|
}
|
|
732
762
|
|
|
733
763
|
private _stopHeaderToggle(event: Event) {
|
|
@@ -750,10 +780,52 @@ export class NileDetail extends NileElement {
|
|
|
750
780
|
await animateShow(this);
|
|
751
781
|
} else {
|
|
752
782
|
await animateHide(this);
|
|
783
|
+
// In preview mode the details element stays open so the preview remains visible.
|
|
784
|
+
this._detailOpen = this._previewEnabled;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
@watch(['preview', 'previewPercentage'], { waitUntilFirstUpdate: true })
|
|
789
|
+
handlePreviewChange() {
|
|
790
|
+
if (this.open) {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (this._previewEnabled) {
|
|
794
|
+
this._detailOpen = true;
|
|
795
|
+
this._applyPreviewHeight();
|
|
796
|
+
} else {
|
|
797
|
+
this.body.hidden = true;
|
|
798
|
+
this.body.style.height = '0';
|
|
753
799
|
this._detailOpen = false;
|
|
754
800
|
}
|
|
755
801
|
}
|
|
756
802
|
|
|
803
|
+
/** Measures the content and clamps the body to the configured preview height. */
|
|
804
|
+
private async _applyPreviewHeight() {
|
|
805
|
+
await this.updateComplete;
|
|
806
|
+
if (!this._isPreviewActive || !this.body) {
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
this.body.hidden = false;
|
|
810
|
+
this.body.style.height = `${getPreviewHeight(this)}px`;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
private _handlePreviewClick() {
|
|
814
|
+
if (this._isPreviewActive && !this.disabled) {
|
|
815
|
+
showDetail(this);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
private _handlePreviewKeyDown(event: KeyboardEvent) {
|
|
820
|
+
if (!this._isPreviewActive || this.disabled) {
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
824
|
+
event.preventDefault();
|
|
825
|
+
showDetail(this);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
757
829
|
async show() {
|
|
758
830
|
return showDetail(this);
|
|
759
831
|
}
|
|
@@ -1017,6 +1089,7 @@ export class NileDetail extends NileElement {
|
|
|
1017
1089
|
'detail--disabled': this.disabled,
|
|
1018
1090
|
'detail--selection': isSelection,
|
|
1019
1091
|
'detail--light': this._isLightVariant,
|
|
1092
|
+
'detail--preview': this._isPreviewActive,
|
|
1020
1093
|
})}
|
|
1021
1094
|
>
|
|
1022
1095
|
<summary
|
|
@@ -1062,7 +1135,18 @@ export class NileDetail extends NileElement {
|
|
|
1062
1135
|
|
|
1063
1136
|
</summary>
|
|
1064
1137
|
|
|
1065
|
-
<div
|
|
1138
|
+
<div
|
|
1139
|
+
part="content"
|
|
1140
|
+
class=${classMap({
|
|
1141
|
+
'detail__body': true,
|
|
1142
|
+
'detail__body--preview': this._isPreviewActive,
|
|
1143
|
+
})}
|
|
1144
|
+
role=${this._isPreviewActive ? 'button' : nothing}
|
|
1145
|
+
tabindex=${this._isPreviewActive && !this.disabled ? '0' : nothing}
|
|
1146
|
+
aria-label=${this._isPreviewActive ? 'Expand to view full content' : nothing}
|
|
1147
|
+
@click=${this._handlePreviewClick}
|
|
1148
|
+
@keydown=${this._handlePreviewKeyDown}
|
|
1149
|
+
>
|
|
1066
1150
|
${isSelection
|
|
1067
1151
|
? html`<div part="selection-content" class="detail__selection-content">${this._renderSelectionBody()}</div>`
|
|
1068
1152
|
: ''}
|
|
@@ -2,9 +2,20 @@ import { animateTo, shimKeyframesHeightAuto, stopAnimations } from '../internal/
|
|
|
2
2
|
import { getAnimation, setDefaultAnimation } from '../utilities/animation-registry';
|
|
3
3
|
import { waitForEvent } from '../internal/event';
|
|
4
4
|
import type { NileDetail } from './nile-detail';
|
|
5
|
+
export function getPreviewHeight(component: NileDetail): number {
|
|
6
|
+
if (!component.preview) {
|
|
7
|
+
return 0;
|
|
8
|
+
}
|
|
9
|
+
const pct = Math.min(100, Math.max(0, component.previewPercentage));
|
|
10
|
+
if (pct <= 0) {
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
return Math.max(1, Math.round((component.body.scrollHeight * pct) / 100));
|
|
14
|
+
}
|
|
5
15
|
|
|
6
16
|
/*
|
|
7
17
|
Runs the show animation on the detail body.
|
|
18
|
+
In preview mode the animation starts from the preview height instead of 0.
|
|
8
19
|
Emits nile-show (cancelable) before and nile-after-show after the animation.
|
|
9
20
|
*/
|
|
10
21
|
export async function animateShow(component: NileDetail): Promise<void> {
|
|
@@ -17,8 +28,15 @@ export async function animateShow(component: NileDetail): Promise<void> {
|
|
|
17
28
|
await stopAnimations(component.body);
|
|
18
29
|
component.body.hidden = false;
|
|
19
30
|
|
|
31
|
+
const previewHeight = getPreviewHeight(component);
|
|
20
32
|
const { keyframes, options } = getAnimation(component, 'detail.show', { dir: 'ltr' });
|
|
21
|
-
|
|
33
|
+
const frames = previewHeight > 0
|
|
34
|
+
? [
|
|
35
|
+
{ height: `${previewHeight}px`, opacity: '1' },
|
|
36
|
+
{ height: 'auto', opacity: '1' }
|
|
37
|
+
]
|
|
38
|
+
: keyframes;
|
|
39
|
+
await animateTo(component.body, shimKeyframesHeightAuto(frames, component.body.scrollHeight), options);
|
|
22
40
|
component.body.style.height = 'auto';
|
|
23
41
|
|
|
24
42
|
component.emit('nile-after-show');
|
|
@@ -26,6 +44,7 @@ export async function animateShow(component: NileDetail): Promise<void> {
|
|
|
26
44
|
|
|
27
45
|
/*
|
|
28
46
|
Runs the hide animation on the detail body.
|
|
47
|
+
In preview mode the body collapses to the preview height and stays visible.
|
|
29
48
|
Emits nile-hide (cancelable) before and nile-after-hide after the animation.
|
|
30
49
|
*/
|
|
31
50
|
export async function animateHide(component: NileDetail): Promise<void> {
|
|
@@ -37,10 +56,21 @@ export async function animateHide(component: NileDetail): Promise<void> {
|
|
|
37
56
|
|
|
38
57
|
await stopAnimations(component.body);
|
|
39
58
|
|
|
59
|
+
const previewHeight = getPreviewHeight(component);
|
|
40
60
|
const { keyframes, options } = getAnimation(component, 'detail.hide', { dir: 'ltr' });
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
|
|
62
|
+
if (previewHeight > 0) {
|
|
63
|
+
const frames = [
|
|
64
|
+
{ height: 'auto', opacity: '1' },
|
|
65
|
+
{ height: `${previewHeight}px`, opacity: '1' }
|
|
66
|
+
];
|
|
67
|
+
await animateTo(component.body, shimKeyframesHeightAuto(frames, component.body.scrollHeight), options);
|
|
68
|
+
component.body.style.height = `${previewHeight}px`;
|
|
69
|
+
} else {
|
|
70
|
+
await animateTo(component.body, shimKeyframesHeightAuto(keyframes, component.body.scrollHeight), options);
|
|
71
|
+
component.body.hidden = true;
|
|
72
|
+
component.body.style.height = 'auto';
|
|
73
|
+
}
|
|
44
74
|
|
|
45
75
|
component.emit('nile-after-hide');
|
|
46
76
|
}
|
|
@@ -14,12 +14,31 @@ export const styles = css`
|
|
|
14
14
|
display: block;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/* Field header */
|
|
18
|
+
|
|
19
|
+
.field-header {
|
|
20
|
+
display: flex;
|
|
21
|
+
justify-content: space-between;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
24
|
+
margin-bottom: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.field-label {
|
|
28
|
+
font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
|
|
29
|
+
font-size: var(--nile-type-scale-3, var(--ng-font-size-text-sm));
|
|
30
|
+
font-weight: var(--nile-font-weight-medium, var(--ng-font-weight-medium));
|
|
31
|
+
color: var(--nile-colors-dark-900, var(--ng-colors-text-secondary-700));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Layout */
|
|
35
|
+
|
|
17
36
|
.container {
|
|
18
37
|
display: flex;
|
|
19
38
|
justify-content: center;
|
|
20
39
|
align-items: center;
|
|
21
|
-
gap:
|
|
22
|
-
height:
|
|
40
|
+
gap: var(--nile-spacing-md, var(--ng-spacing-md));
|
|
41
|
+
min-height: var(--nile-spacing-5xl, var(--ng-spacing-5xl));
|
|
23
42
|
}
|
|
24
43
|
|
|
25
44
|
.align-item-center {
|
|
@@ -27,14 +46,14 @@ export const styles = css`
|
|
|
27
46
|
}
|
|
28
47
|
|
|
29
48
|
slot.span {
|
|
30
|
-
font-size: var(--nile-font-size-micro);
|
|
31
|
-
margin-top: 14px;
|
|
49
|
+
font-size: var(--nile-font-size-micro, var(--ng-font-size-text-xs));
|
|
32
50
|
}
|
|
33
51
|
|
|
34
52
|
.range-container {
|
|
35
53
|
display: flex;
|
|
36
54
|
flex-direction: column;
|
|
37
|
-
|
|
55
|
+
flex: 1 1 auto;
|
|
56
|
+
gap: var(--nile-spacing-sm, var(--ng-spacing-sm));
|
|
38
57
|
}
|
|
39
58
|
|
|
40
59
|
.column-reverse {
|
|
@@ -47,18 +66,21 @@ export const styles = css`
|
|
|
47
66
|
}
|
|
48
67
|
|
|
49
68
|
.label-container span {
|
|
50
|
-
margin: var(--nile-spacing-none);
|
|
51
|
-
padding: var(--nile-spacing-none);
|
|
52
|
-
font-size: var(--nile-font-size-micro);
|
|
69
|
+
margin: var(--nile-spacing-none, var(--ng-spacing-none));
|
|
70
|
+
padding: var(--nile-spacing-none, var(--ng-spacing-none));
|
|
71
|
+
font-size: var(--nile-font-size-micro, var(--ng-font-size-text-xs));
|
|
72
|
+
color: var(--nile-colors-dark-500, var(--ng-colors-text-tertiary-600));
|
|
53
73
|
}
|
|
54
74
|
|
|
75
|
+
/* track & fill */
|
|
76
|
+
|
|
55
77
|
.range {
|
|
56
78
|
position: relative;
|
|
57
|
-
width: 228px;
|
|
58
|
-
height:
|
|
59
|
-
background-color: var(--nile-colors-neutral-400);
|
|
79
|
+
width: var(--nile-slider-width, 228px);
|
|
80
|
+
height: var(--nile-spacing-xs, var(--ng-spacing-sm));
|
|
81
|
+
background-color: var(--nile-colors-neutral-400, var(--ng-colors-bg-quaternary));
|
|
60
82
|
user-select: none;
|
|
61
|
-
border-radius: var(--nile-radius-radius-3xl);
|
|
83
|
+
border-radius: var(--nile-radius-radius-3xl, var(--ng-radius-full));
|
|
62
84
|
}
|
|
63
85
|
|
|
64
86
|
.range:hover {
|
|
@@ -69,50 +91,149 @@ export const styles = css`
|
|
|
69
91
|
position: absolute;
|
|
70
92
|
height: 100%;
|
|
71
93
|
width: 0%;
|
|
72
|
-
background-color: var(--nile-colors-primary-600);
|
|
94
|
+
background-color: var(--nile-colors-primary-600, var(--ng-colors-bg-brand-solid));
|
|
73
95
|
top: 0px;
|
|
74
96
|
left: 0px;
|
|
75
97
|
z-index: 98;
|
|
76
|
-
border-radius: var(--nile-radius-radius-3xl);
|
|
98
|
+
border-radius: var(--nile-radius-radius-3xl, var(--ng-radius-full));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* ------------------------------------------------------------------ */
|
|
102
|
+
/* Inline value label (valueLabel="bottom") */
|
|
103
|
+
/* ------------------------------------------------------------------ */
|
|
104
|
+
|
|
105
|
+
.value-label {
|
|
106
|
+
position: absolute;
|
|
107
|
+
/* Start at the track bottom, then push down past the handle and the
|
|
108
|
+
largest (pressed, 8px) ring */
|
|
109
|
+
top: 100%;
|
|
110
|
+
margin-top: var(--nile-spacing-xl, var(--ng-spacing-xl));
|
|
111
|
+
transform: translateX(-50%);
|
|
112
|
+
font-family: var(--nile-font-family-serif, var(--ng-font-family-body));
|
|
113
|
+
font-size: var(--nile-font-size-micro, var(--ng-font-size-text-xs));
|
|
114
|
+
font-variant-numeric: tabular-nums;
|
|
115
|
+
color: var(--nile-colors-dark-500, var(--ng-colors-text-quaternary-500));
|
|
116
|
+
white-space: nowrap;
|
|
117
|
+
pointer-events: none;
|
|
118
|
+
user-select: none;
|
|
119
|
+
-webkit-user-select: none;
|
|
77
120
|
}
|
|
78
121
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
122
|
+
/* Reserve room below the track for the inline value label */
|
|
123
|
+
:host([valuelabel='bottom']) .container {
|
|
124
|
+
padding-bottom: var(--nile-spacing-2xl, var(--ng-spacing-2xl));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* Handles */
|
|
128
|
+
|
|
129
|
+
.range-button,
|
|
130
|
+
.range-button-two {
|
|
131
|
+
height: var(--nile-spacing-lg, var(--ng-spacing-2xl));
|
|
132
|
+
width: var(--nile-spacing-lg, var(--ng-spacing-2xl));
|
|
133
|
+
box-sizing: border-box;
|
|
134
|
+
/* Enterprise: solid brand dot - NextGen: white fill + brand border */
|
|
135
|
+
background-color: var(--nile-colors-primary-600, var(--ng-colors-bg-primary));
|
|
136
|
+
border: var(--nile-spacing-xxs, var(--ng-spacing-xxs)) solid
|
|
137
|
+
var(--nile-colors-primary-600, var(--ng-colors-border-brand-alt));
|
|
83
138
|
position: absolute;
|
|
84
139
|
top: 50%;
|
|
85
140
|
transform: translate(-50%, -50%);
|
|
86
|
-
border-radius: var(--nile-radius-radius-3xl);
|
|
141
|
+
border-radius: var(--nile-radius-radius-3xl, var(--ng-radius-full));
|
|
87
142
|
left: 0;
|
|
88
143
|
z-index: 100;
|
|
89
|
-
|
|
90
|
-
transition:
|
|
144
|
+
cursor: grab;
|
|
145
|
+
transition:
|
|
146
|
+
box-shadow var(--nile-transition-duration-short, 120ms) ease,
|
|
147
|
+
background-color var(--nile-transition-duration-short, 120ms) ease,
|
|
148
|
+
transform var(--nile-transition-duration-shorter, 80ms) ease;
|
|
91
149
|
}
|
|
92
150
|
|
|
93
|
-
.range-button
|
|
94
|
-
|
|
95
|
-
background-color: var(--nile-colors-primary-700);
|
|
151
|
+
.range-button-two {
|
|
152
|
+
left: 100%;
|
|
96
153
|
}
|
|
97
154
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
155
|
+
/* Hover: ring (Enterprise 2px - NextGen 6px) */
|
|
156
|
+
.range-button:hover,
|
|
157
|
+
.range-button-two:hover {
|
|
158
|
+
cursor: grab;
|
|
159
|
+
box-shadow: 0 0 0 var(--nile-spacing-xxs, var(--ng-spacing-sm))
|
|
160
|
+
var(--nile-colors-primary-100, var(--ng-colors-bg-brand-secondary));
|
|
102
161
|
}
|
|
103
162
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
163
|
+
/* Focused: theme focus ring */
|
|
164
|
+
.range-button:focus-visible,
|
|
165
|
+
.range-button-two:focus-visible {
|
|
166
|
+
outline: none;
|
|
167
|
+
box-shadow: var(--nile-focus-ring,
|
|
168
|
+
var(--ng-focus-ring,
|
|
169
|
+
0 0 0 var(--nile-spacing-xs) var(--nile-colors-primary-100)));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* Pressed: ring (Enterprise 4px - NextGen 8px) + 1.1x scale */
|
|
173
|
+
.range-button:active,
|
|
174
|
+
.range-button-two:active {
|
|
175
|
+
cursor: grabbing;
|
|
176
|
+
transform: translate(-50%, -50%) scale(1.1);
|
|
177
|
+
box-shadow: 0 0 0 var(--nile-spacing-xs, var(--ng-spacing-md))
|
|
178
|
+
var(--nile-colors-primary-100, var(--ng-colors-bg-brand-secondary));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* Error state */
|
|
182
|
+
:host([error]) .range-completed {
|
|
183
|
+
background-color: var(--nile-colors-red-700, var(--ng-colors-bg-error-solid));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
:host([error]) .range-button,
|
|
187
|
+
:host([error]) .range-button-two {
|
|
188
|
+
background-color: var(--nile-colors-red-700, var(--ng-colors-bg-primary));
|
|
189
|
+
border-color: var(--nile-colors-red-700, var(--ng-colors-border-error));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
:host([error]) .range-button:hover,
|
|
193
|
+
:host([error]) .range-button-two:hover {
|
|
194
|
+
box-shadow: 0 0 0 var(--nile-spacing-xxs, var(--ng-spacing-sm))
|
|
195
|
+
var(--nile-colors-red-100, var(--ng-colors-bg-error-secondary, var(--ng-color-error-100)));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
:host([error]) .range-button:focus-visible,
|
|
199
|
+
:host([error]) .range-button-two:focus-visible {
|
|
200
|
+
box-shadow: var(--nile-focus-ring-error,
|
|
201
|
+
var(--ng-focus-ring-error,
|
|
202
|
+
0 0 0 var(--nile-spacing-xs) var(--nile-colors-red-100)));
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Disabled state */
|
|
206
|
+
:host([disabled]) .range,
|
|
207
|
+
:host([disabled]) .range:hover {
|
|
208
|
+
cursor: not-allowed;
|
|
209
|
+
background-color: var(--nile-colors-neutral-100, var(--ng-colors-bg-disabled));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
:host([disabled]) .range-completed {
|
|
213
|
+
background-color: var(--nile-colors-neutral-500, var(--ng-colors-fg-disabled));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
:host([disabled]) .range-button,
|
|
217
|
+
:host([disabled]) .range-button-two {
|
|
218
|
+
background-color: var(--nile-colors-neutral-500, var(--ng-colors-bg-primary));
|
|
219
|
+
border-color: var(--nile-colors-neutral-500, var(--ng-colors-border-disabled));
|
|
220
|
+
cursor: not-allowed;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
:host([disabled]) .range-button:hover,
|
|
224
|
+
:host([disabled]) .range-button-two:hover,
|
|
225
|
+
:host([disabled]) .range-button:active,
|
|
226
|
+
:host([disabled]) .range-button-two:active {
|
|
227
|
+
box-shadow: none;
|
|
110
228
|
transform: translate(-50%, -50%);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
:host([disabled]) .field-label,
|
|
232
|
+
:host([disabled]) .value-label,
|
|
233
|
+
:host([disabled]) .label-container span {
|
|
234
|
+
color: var(--nile-colors-neutral-500, var(--ng-colors-fg-disabled));
|
|
235
|
+
user-select: none;
|
|
236
|
+
-webkit-user-select: none;
|
|
116
237
|
}
|
|
117
238
|
`;
|
|
118
239
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { TemplateResult, html } from 'lit';
|
|
2
2
|
import NileSlider from './nile-slider';
|
|
3
3
|
import { classMap } from 'lit/directives/class-map.js';
|
|
4
|
+
import { valueToPercent } from './utils/nile-slider.utils';
|
|
5
|
+
|
|
6
|
+
const tooltipDisabled = (nileSlider: NileSlider): boolean =>
|
|
7
|
+
nileSlider.disabled || nileSlider.valueLabel !== 'tooltip';
|
|
4
8
|
|
|
5
9
|
export const rangeSlider = (nileSlider: NileSlider): TemplateResult => {
|
|
6
10
|
return html`
|
|
@@ -8,6 +12,7 @@ export const rangeSlider = (nileSlider: NileSlider): TemplateResult => {
|
|
|
8
12
|
<nile-tooltip
|
|
9
13
|
content=${nileSlider.rangeOneValue}
|
|
10
14
|
placement=${nileSlider.tooltipPosition}
|
|
15
|
+
?disabled=${tooltipDisabled(nileSlider)}
|
|
11
16
|
>
|
|
12
17
|
<div
|
|
13
18
|
id="range-one"
|
|
@@ -24,6 +29,7 @@ export const rangeSlider = (nileSlider: NileSlider): TemplateResult => {
|
|
|
24
29
|
<nile-tooltip
|
|
25
30
|
content=${nileSlider.rangeTwoValue}
|
|
26
31
|
placement=${nileSlider.tooltipPosition}
|
|
32
|
+
?disabled=${tooltipDisabled(nileSlider)}
|
|
27
33
|
>
|
|
28
34
|
<div
|
|
29
35
|
id="range-two"
|
|
@@ -47,6 +53,7 @@ export const singleSlider = (nileSlider: NileSlider): TemplateResult => {
|
|
|
47
53
|
<nile-tooltip
|
|
48
54
|
content=${nileSlider.value}
|
|
49
55
|
placement=${nileSlider.tooltipPosition}
|
|
56
|
+
?disabled=${tooltipDisabled(nileSlider)}
|
|
50
57
|
>
|
|
51
58
|
<div
|
|
52
59
|
class=${classMap({
|
|
@@ -59,7 +66,7 @@ export const singleSlider = (nileSlider: NileSlider): TemplateResult => {
|
|
|
59
66
|
aria-valuemin=${nileSlider.minValue}
|
|
60
67
|
aria-valuemax=${nileSlider.maxValue}
|
|
61
68
|
aria-valuenow=${nileSlider.value}
|
|
62
|
-
aria-label=${nileSlider.ariaLabel || "Slider value"}
|
|
69
|
+
aria-label=${nileSlider.ariaLabel || nileSlider.label || "Slider value"}
|
|
63
70
|
></div>
|
|
64
71
|
</nile-tooltip>
|
|
65
72
|
</div>
|
|
@@ -74,4 +81,40 @@ export const lableContaier = (nileSlider: NileSlider): TemplateResult => {
|
|
|
74
81
|
<span id="label-end">${nileSlider.labelEnd}</span>
|
|
75
82
|
</div>
|
|
76
83
|
`;
|
|
77
|
-
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
export const fieldHeader = (nileSlider: NileSlider): TemplateResult => {
|
|
88
|
+
return html`
|
|
89
|
+
<div part="field-header" class="field-header">
|
|
90
|
+
<label id="field-label" part="field-label" class="field-label">
|
|
91
|
+
${nileSlider.label}
|
|
92
|
+
</label>
|
|
93
|
+
</div>
|
|
94
|
+
`;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
export const bottomValueLabels = (nileSlider: NileSlider): TemplateResult => {
|
|
99
|
+
if (!nileSlider.rangeSlider) {
|
|
100
|
+
return html`
|
|
101
|
+
<span
|
|
102
|
+
part="value-label"
|
|
103
|
+
class="value-label"
|
|
104
|
+
style="left: ${valueToPercent(nileSlider.value, nileSlider)}%"
|
|
105
|
+
>${nileSlider.value}</span>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
return html`
|
|
109
|
+
<span
|
|
110
|
+
part="value-label"
|
|
111
|
+
class="value-label"
|
|
112
|
+
style="left: ${valueToPercent(nileSlider.rangeOneValue, nileSlider)}%"
|
|
113
|
+
>${nileSlider.rangeOneValue}</span>
|
|
114
|
+
<span
|
|
115
|
+
part="value-label"
|
|
116
|
+
class="value-label"
|
|
117
|
+
style="left: ${valueToPercent(nileSlider.rangeTwoValue, nileSlider)}%"
|
|
118
|
+
>${nileSlider.rangeTwoValue}</span>
|
|
119
|
+
`;
|
|
120
|
+
};
|