@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.
Files changed (56) hide show
  1. package/README.md +6 -0
  2. package/dist/index.js +370 -177
  3. package/dist/nile-detail/nile-detail.cjs.js +1 -1
  4. package/dist/nile-detail/nile-detail.cjs.js.map +1 -1
  5. package/dist/nile-detail/nile-detail.css.cjs.js +1 -1
  6. package/dist/nile-detail/nile-detail.css.cjs.js.map +1 -1
  7. package/dist/nile-detail/nile-detail.css.esm.js +37 -1
  8. package/dist/nile-detail/nile-detail.esm.js +17 -9
  9. package/dist/nile-detail/nile-detail.utils.cjs.js +1 -1
  10. package/dist/nile-detail/nile-detail.utils.cjs.js.map +1 -1
  11. package/dist/nile-detail/nile-detail.utils.esm.js +1 -1
  12. package/dist/nile-slider/nile-slider.cjs.js +1 -1
  13. package/dist/nile-slider/nile-slider.cjs.js.map +1 -1
  14. package/dist/nile-slider/nile-slider.css.cjs.js +1 -1
  15. package/dist/nile-slider/nile-slider.css.cjs.js.map +1 -1
  16. package/dist/nile-slider/nile-slider.css.esm.js +162 -41
  17. package/dist/nile-slider/nile-slider.esm.js +5 -3
  18. package/dist/nile-slider/nile-slider.template.cjs.js +1 -1
  19. package/dist/nile-slider/nile-slider.template.cjs.js.map +1 -1
  20. package/dist/nile-slider/nile-slider.template.esm.js +49 -23
  21. package/dist/nile-slider/utils/nile-slider.utils.cjs.js +1 -1
  22. package/dist/nile-slider/utils/nile-slider.utils.cjs.js.map +1 -1
  23. package/dist/nile-slider/utils/nile-slider.utils.esm.js +1 -1
  24. package/dist/src/nile-detail/nile-detail.css.js +37 -1
  25. package/dist/src/nile-detail/nile-detail.css.js.map +1 -1
  26. package/dist/src/nile-detail/nile-detail.d.ts +15 -0
  27. package/dist/src/nile-detail/nile-detail.js +85 -4
  28. package/dist/src/nile-detail/nile-detail.js.map +1 -1
  29. package/dist/src/nile-detail/nile-detail.utils.d.ts +1 -0
  30. package/dist/src/nile-detail/nile-detail.utils.js +34 -4
  31. package/dist/src/nile-detail/nile-detail.utils.js.map +1 -1
  32. package/dist/src/nile-slider/nile-slider.css.js +160 -39
  33. package/dist/src/nile-slider/nile-slider.css.js.map +1 -1
  34. package/dist/src/nile-slider/nile-slider.d.ts +5 -1
  35. package/dist/src/nile-slider/nile-slider.js +23 -1
  36. package/dist/src/nile-slider/nile-slider.js.map +1 -1
  37. package/dist/src/nile-slider/nile-slider.template.d.ts +2 -0
  38. package/dist/src/nile-slider/nile-slider.template.js +38 -1
  39. package/dist/src/nile-slider/nile-slider.template.js.map +1 -1
  40. package/dist/src/nile-slider/types/nile-slider.types.d.ts +1 -0
  41. package/dist/src/nile-slider/types/nile-slider.types.js.map +1 -1
  42. package/dist/src/nile-slider/utils/nile-slider.utils.js +4 -0
  43. package/dist/src/nile-slider/utils/nile-slider.utils.js.map +1 -1
  44. package/dist/src/version.js +1 -1
  45. package/dist/src/version.js.map +1 -1
  46. package/dist/tsconfig.tsbuildinfo +1 -1
  47. package/package.json +1 -1
  48. package/src/nile-detail/nile-detail.css.ts +37 -1
  49. package/src/nile-detail/nile-detail.ts +87 -3
  50. package/src/nile-detail/nile-detail.utils.ts +34 -4
  51. package/src/nile-slider/nile-slider.css.ts +160 -39
  52. package/src/nile-slider/nile-slider.template.ts +45 -2
  53. package/src/nile-slider/nile-slider.ts +11 -3
  54. package/src/nile-slider/types/nile-slider.types.ts +2 -0
  55. package/src/nile-slider/utils/nile-slider.utils.ts +2 -0
  56. package/vscode-html-custom-data.json +48 -10
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Webcomponent nile-elements following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "nile-elements",
6
- "version": "1.8.1",
6
+ "version": "1.8.3",
7
7
  "main": "dist/src/index.js",
8
8
  "type": "module",
9
9
  "module": "dist/src/index.js",
@@ -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 part="content" class="detail__body">
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
- await animateTo(component.body, shimKeyframesHeightAuto(keyframes, component.body.scrollHeight), options);
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
- await animateTo(component.body, shimKeyframesHeightAuto(keyframes, component.body.scrollHeight), options);
42
- component.body.hidden = true;
43
- component.body.style.height = 'auto';
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: 10px;
22
- height: 100px;
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
- gap: var(--nile-spacing-sm);
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: 4px;
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
- .range-button {
80
- height: 12px;
81
- width: 12px;
82
- background-color: var(--nile-colors-primary-600);
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
- box-shadow: rgba(0, 82, 145, 0.1) 0px 1px 2px 0px, rgba(0, 94, 166, 0.15) 0px 0px 0px 2px;
90
- transition: box-shadow var(--nile-transition-duration-default) ease;
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:hover, .range-button-two:hover {
94
- cursor: pointer;
95
- background-color: var(--nile-colors-primary-700);
151
+ .range-button-two {
152
+ left: 100%;
96
153
  }
97
154
 
98
- .range-button:active, .range-button-two:active {
99
- transition: box-shadow var(--nile-transition-duration-default) ease;
100
- background-color: var(--nile-colors-primary-700);
101
- box-shadow: rgba(0, 82, 145, 0.1) 0px 1px 2px 0px, rgba(0, 94, 166, 0.15) 0px 0px 0px 4px;
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
- .range-button-two {
105
- height: 12px;
106
- width: 12px;
107
- background-color: var(--nile-colors-primary-600);
108
- position: absolute;
109
- top: 50%;
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
- border-radius: var(--nile-radius-radius-3xl);
112
- left: 100%;
113
- z-index: 100;
114
- box-shadow: rgba(0, 82, 145, 0.1) 0px 1px 2px 0px, rgba(0, 94, 166, 0.15) 0px 0px 0px 2px;
115
- transition: box-shadow var(--nile-transition-duration-default) ease;
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
+ };