ng-primitives 0.95.0 → 0.97.0

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.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, computed, Directive, input, numberAttribute, output, booleanAttribute, HostListener } from '@angular/core';
2
+ import { signal, computed, Directive, input, numberAttribute, output, booleanAttribute } from '@angular/core';
3
3
  import { injectElementRef } from 'ng-primitives/internal';
4
- import { createPrimitive, controlled, emitter, attrBinding, dataBinding, deprecatedSetter, styleBinding, listener, createStateToken, createStateProvider, createStateInjector, createState } from 'ng-primitives/state';
4
+ import { createPrimitive, controlled, emitter, attrBinding, dataBinding, deprecatedSetter, styleBinding, listener, onDestroy } from 'ng-primitives/state';
5
5
  import { ngpFormControl } from 'ng-primitives/form-field';
6
6
  import { uniqueId } from 'ng-primitives/utils';
7
7
  import { ngpInteractions } from 'ng-primitives/interactions';
@@ -32,9 +32,11 @@ const [NgpSliderStateToken, ngpSlider, injectSliderState, provideSliderState] =
32
32
  }
33
33
  function setValue(newValue) {
34
34
  const clamped = Math.min(max(), Math.max(min(), newValue));
35
- value.set(clamped);
36
- onValueChange?.(clamped);
37
- valueChange.emit(clamped);
35
+ const stepped = Math.round((clamped - min()) / step()) * step() + min();
36
+ const finalValue = Math.min(max(), Math.max(min(), stepped));
37
+ value.set(finalValue);
38
+ onValueChange?.(finalValue);
39
+ valueChange.emit(finalValue);
38
40
  }
39
41
  function setDisabled(isDisabled) {
40
42
  disabled.set(isDisabled);
@@ -366,266 +368,329 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
366
368
  }]
367
369
  }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSliderValue", required: false }] }], valueChange: [{ type: i0.Output, args: ["ngpSliderValueChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSliderMin", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSliderMax", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSliderStep", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSliderOrientation", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSliderDisabled", required: false }] }] } });
368
370
 
369
- /**
370
- * The state token for the Range Slider primitive.
371
- */
372
- const NgpRangeSliderStateToken = createStateToken('RangeSlider');
373
- /**
374
- * Provides the Range Slider state.
375
- */
376
- const provideRangeSliderState = createStateProvider(NgpRangeSliderStateToken);
377
- /**
378
- * Injects the Range Slider state.
379
- */
380
- const injectRangeSliderState = createStateInjector(NgpRangeSliderStateToken);
381
- /**
382
- * The Range Slider state registration function.
383
- */
384
- const rangeSliderState = createState(NgpRangeSliderStateToken);
371
+ const [NgpRangeSliderStateToken, ngpRangeSlider, injectRangeSliderState, provideRangeSliderState,] = createPrimitive('NgpRangeSlider', ({ id = signal(uniqueId('ngp-range-slider')), low: _low = signal(0), high: _high = signal(100), min = signal(0), max = signal(100), step = signal(1), orientation: _orientation = signal('horizontal'), disabled: _disabled = signal(false), onLowChange, onHighChange, }) => {
372
+ console.log('Creating RangeSliderState', _low(), _high(), min(), max());
373
+ const element = injectElementRef();
374
+ const low = controlled(_low);
375
+ const high = controlled(_high);
376
+ const disabled = controlled(_disabled);
377
+ const orientation = controlled(_orientation);
378
+ const lowChange = emitter();
379
+ const highChange = emitter();
380
+ const track = signal(undefined, ...(ngDevMode ? [{ debugName: "track" }] : []));
381
+ const thumbs = signal([], ...(ngDevMode ? [{ debugName: "thumbs" }] : []));
382
+ // Form control integration
383
+ const status = ngpFormControl({ id, disabled });
384
+ const lowPercentage = computed(() => {
385
+ const range = max() - min();
386
+ if (range <= 0)
387
+ return 0;
388
+ return ((low() - min()) / range) * 100;
389
+ }, ...(ngDevMode ? [{ debugName: "lowPercentage" }] : []));
390
+ const highPercentage = computed(() => {
391
+ const range = max() - min();
392
+ if (range <= 0)
393
+ return 100;
394
+ return ((high() - min()) / range) * 100;
395
+ }, ...(ngDevMode ? [{ debugName: "highPercentage" }] : []));
396
+ const rangePercentage = computed(() => highPercentage() - lowPercentage(), ...(ngDevMode ? [{ debugName: "rangePercentage" }] : []));
397
+ // Host bindings
398
+ attrBinding(element, 'id', id);
399
+ dataBinding(element, 'data-orientation', orientation);
400
+ dataBinding(element, 'data-disabled', status().disabled);
401
+ function setLowValue(value) {
402
+ const clampedValue = Math.max(min(), Math.min(value, high()));
403
+ const steppedValue = Math.round((clampedValue - min()) / step()) * step() + min();
404
+ low.set(steppedValue);
405
+ onLowChange?.(steppedValue);
406
+ lowChange.emit(steppedValue);
407
+ }
408
+ function setHighValue(value) {
409
+ const clampedValue = Math.min(max(), Math.max(value, low()));
410
+ const steppedValue = Math.round((clampedValue - min()) / step()) * step() + min();
411
+ high.set(steppedValue);
412
+ onHighChange?.(steppedValue);
413
+ highChange.emit(steppedValue);
414
+ }
415
+ function getClosestThumb(percentage) {
416
+ const value = min() + (max() - min()) * (percentage / 100);
417
+ const distanceToLow = Math.abs(value - low());
418
+ const distanceToHigh = Math.abs(value - high());
419
+ return distanceToLow <= distanceToHigh ? 'low' : 'high';
420
+ }
421
+ function addThumb(thumb) {
422
+ thumbs.update(t => [...t, thumb]);
423
+ }
424
+ function removeThumb(thumb) {
425
+ thumbs.update(t => t.filter(existing => existing !== thumb));
426
+ }
427
+ function setDisabled(isDisabled) {
428
+ disabled.set(isDisabled);
429
+ }
430
+ function setOrientation(newOrientation) {
431
+ orientation.set(newOrientation);
432
+ }
433
+ function setTrack(newTrack) {
434
+ track.set(newTrack);
435
+ }
436
+ return {
437
+ id,
438
+ low,
439
+ high,
440
+ min,
441
+ max,
442
+ step,
443
+ orientation: deprecatedSetter(orientation, 'setOrientation'),
444
+ disabled: deprecatedSetter(disabled, 'setDisabled'),
445
+ lowPercentage,
446
+ highPercentage,
447
+ rangePercentage,
448
+ track,
449
+ thumbs,
450
+ lowChange: lowChange.asObservable(),
451
+ highChange: highChange.asObservable(),
452
+ setLowValue,
453
+ setHighValue,
454
+ getClosestThumb,
455
+ addThumb,
456
+ removeThumb,
457
+ setDisabled,
458
+ setOrientation,
459
+ setTrack,
460
+ };
461
+ });
462
+
463
+ const [NgpRangeSliderRangeStateToken, ngpRangeSliderRange, injectRangeSliderRangeState, provideRangeSliderRangeState,] = createPrimitive('NgpRangeSliderRange', ({}) => {
464
+ const element = injectElementRef();
465
+ const rangeSlider = injectRangeSliderState();
466
+ // Host bindings
467
+ dataBinding(element, 'data-orientation', () => rangeSlider().orientation());
468
+ dataBinding(element, 'data-disabled', () => rangeSlider().disabled());
469
+ // Horizontal
470
+ styleBinding(element, 'width.%', () => rangeSlider().orientation() === 'horizontal' ? rangeSlider().rangePercentage() : null);
471
+ styleBinding(element, 'inset-inline-start.%', () => rangeSlider().orientation() === 'horizontal' ? rangeSlider().lowPercentage() : null);
472
+ // Vertical
473
+ styleBinding(element, 'height.%', () => rangeSlider().orientation() === 'vertical' ? rangeSlider().rangePercentage() : null);
474
+ styleBinding(element, 'inset-block-start.%', () => rangeSlider().orientation() === 'vertical' ? rangeSlider().lowPercentage() : null);
475
+ return {};
476
+ });
385
477
 
386
478
  /**
387
479
  * Apply the `ngpRangeSliderRange` directive to an element that represents the range between the low and high values.
388
480
  */
389
481
  class NgpRangeSliderRange {
390
482
  constructor() {
391
- /**
392
- * Access the range slider state.
393
- */
394
- this.rangeSliderState = injectRangeSliderState();
483
+ ngpRangeSliderRange({});
395
484
  }
396
485
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpRangeSliderRange, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
397
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgpRangeSliderRange, isStandalone: true, selector: "[ngpRangeSliderRange]", host: { properties: { "attr.data-orientation": "rangeSliderState().orientation()", "attr.data-disabled": "rangeSliderState().disabled() ? \"\" : null", "style.width.%": "rangeSliderState().orientation() === \"horizontal\" ? rangeSliderState().rangePercentage() : undefined", "style.height.%": "rangeSliderState().orientation() === \"vertical\" ? rangeSliderState().rangePercentage() : undefined", "style.inset-inline-start.%": "rangeSliderState().orientation() === \"horizontal\" ? rangeSliderState().lowPercentage() : undefined", "style.inset-block-start.%": "rangeSliderState().orientation() === \"vertical\" ? rangeSliderState().lowPercentage() : undefined" } }, exportAs: ["ngpRangeSliderRange"], ngImport: i0 }); }
486
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgpRangeSliderRange, isStandalone: true, selector: "[ngpRangeSliderRange]", exportAs: ["ngpRangeSliderRange"], ngImport: i0 }); }
398
487
  }
399
488
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpRangeSliderRange, decorators: [{
400
489
  type: Directive,
401
490
  args: [{
402
491
  selector: '[ngpRangeSliderRange]',
403
492
  exportAs: 'ngpRangeSliderRange',
404
- host: {
405
- '[attr.data-orientation]': 'rangeSliderState().orientation()',
406
- '[attr.data-disabled]': 'rangeSliderState().disabled() ? "" : null',
407
- '[style.width.%]': 'rangeSliderState().orientation() === "horizontal" ? rangeSliderState().rangePercentage() : undefined',
408
- '[style.height.%]': 'rangeSliderState().orientation() === "vertical" ? rangeSliderState().rangePercentage() : undefined',
409
- '[style.inset-inline-start.%]': 'rangeSliderState().orientation() === "horizontal" ? rangeSliderState().lowPercentage() : undefined',
410
- '[style.inset-block-start.%]': 'rangeSliderState().orientation() === "vertical" ? rangeSliderState().lowPercentage() : undefined',
411
- },
412
493
  }]
413
- }] });
494
+ }], ctorParameters: () => [] });
414
495
 
415
- /**
416
- * Apply the `ngpRangeSliderThumb` directive to an element that represents a thumb of the range slider.
417
- * Each thumb can be configured to control either the 'low' or 'high' value.
418
- */
419
- class NgpRangeSliderThumb {
420
- constructor() {
421
- /**
422
- * Access the range slider state.
423
- */
424
- this.state = injectRangeSliderState();
425
- /**
426
- * Access the thumb element.
427
- */
428
- this.elementRef = injectElementRef();
429
- /**
430
- * Determines which value this thumb controls ('low' or 'high').
431
- */
432
- this.thumb = computed(() => this.state().thumbs().indexOf(this) === 0 ? 'low' : 'high', ...(ngDevMode ? [{ debugName: "thumb" }] : []));
433
- /**
434
- * Store the dragging state.
435
- */
436
- this.dragging = false;
437
- /**
438
- * Get the current value for this thumb.
439
- */
440
- this.value = computed(() => this.thumb() === 'low' ? this.state().low() : this.state().high(), ...(ngDevMode ? [{ debugName: "value" }] : []));
441
- /**
442
- * Get the current percentage for this thumb.
443
- */
444
- this.percentage = computed(() => this.thumb() === 'low' ? this.state().lowPercentage() : this.state().highPercentage(), ...(ngDevMode ? [{ debugName: "percentage" }] : []));
445
- ngpInteractions({
446
- hover: true,
447
- focusVisible: true,
448
- press: true,
449
- disabled: this.state().disabled,
450
- });
451
- this.state().addThumb(this);
452
- }
453
- ngOnDestroy() {
454
- this.state().removeThumb(this);
455
- }
456
- handlePointerDown(event) {
496
+ const [NgpRangeSliderThumbStateToken, ngpRangeSliderThumb, injectRangeSliderThumbState, provideRangeSliderThumbState,] = createPrimitive('NgpRangeSliderThumb', ({}) => {
497
+ const element = injectElementRef();
498
+ const rangeSlider = injectRangeSliderState();
499
+ // Store dragging state
500
+ let dragging = false;
501
+ // Determine which thumb this is based on registration order
502
+ const thumb = computed(() => (rangeSlider().thumbs().indexOf(element) === 0 ? 'low' : 'high'), ...(ngDevMode ? [{ debugName: "thumb" }] : []));
503
+ const value = computed(() => (thumb() === 'low' ? rangeSlider().low() : rangeSlider().high()), ...(ngDevMode ? [{ debugName: "value" }] : []));
504
+ const percentage = computed(() => thumb() === 'low' ? rangeSlider().lowPercentage() : rangeSlider().highPercentage(), ...(ngDevMode ? [{ debugName: "percentage" }] : []));
505
+ // Setup interactions
506
+ ngpInteractions({
507
+ hover: true,
508
+ focusVisible: true,
509
+ press: true,
510
+ disabled: rangeSlider().disabled,
511
+ });
512
+ // Host bindings
513
+ attrBinding(element, 'role', 'slider');
514
+ attrBinding(element, 'aria-valuemin', () => rangeSlider().min());
515
+ attrBinding(element, 'aria-valuemax', () => rangeSlider().max());
516
+ attrBinding(element, 'aria-valuenow', value);
517
+ attrBinding(element, 'aria-orientation', () => rangeSlider().orientation());
518
+ attrBinding(element, 'tabindex', () => (rangeSlider().disabled() ? -1 : 0));
519
+ dataBinding(element, 'data-orientation', () => rangeSlider().orientation());
520
+ dataBinding(element, 'data-disabled', () => rangeSlider().disabled());
521
+ dataBinding(element, 'data-thumb', thumb);
522
+ styleBinding(element, 'inset-inline-start.%', () => rangeSlider().orientation() === 'horizontal' ? percentage() : null);
523
+ styleBinding(element, 'inset-block-start.%', () => rangeSlider().orientation() === 'vertical' ? percentage() : null);
524
+ function handlePointerDown(event) {
457
525
  event.preventDefault();
458
- if (this.state().disabled()) {
526
+ if (rangeSlider().disabled()) {
459
527
  return;
460
528
  }
461
- this.dragging = true;
529
+ dragging = true;
462
530
  }
463
- handlePointerUp() {
464
- if (this.state().disabled()) {
531
+ function handlePointerUp() {
532
+ if (rangeSlider().disabled()) {
465
533
  return;
466
534
  }
467
- this.dragging = false;
535
+ dragging = false;
468
536
  }
469
- handlePointerMove(event) {
470
- if (this.state().disabled() || !this.dragging) {
537
+ function handlePointerMove(event) {
538
+ if (rangeSlider().disabled() || !dragging) {
471
539
  return;
472
540
  }
473
- const rect = this.state().track()?.element.nativeElement.getBoundingClientRect();
474
- if (!rect) {
541
+ const track = rangeSlider().track();
542
+ if (!track) {
475
543
  return;
476
544
  }
477
- const percentage = this.state().orientation() === 'horizontal'
478
- ? (event.clientX - rect.left) / rect.width
479
- : (event.clientY - rect.top) / rect.height;
480
- const value = this.state().min() +
481
- (this.state().max() - this.state().min()) * Math.max(0, Math.min(1, percentage));
545
+ const rect = track.nativeElement.getBoundingClientRect();
546
+ // Calculate the pointer position as a percentage of the track
547
+ // p.ex. for horizontal: (pointerX - trackLeft) / trackWidth
548
+ const percentage = rangeSlider().orientation() === 'horizontal'
549
+ ? ((event.clientX - rect.left) / rect.width) * 100
550
+ : ((event.clientY - rect.top) / rect.height) * 100;
551
+ const min = rangeSlider().min();
552
+ const max = rangeSlider().max();
553
+ const rangeSize = max - min;
554
+ const clampedPercentage = Math.max(0, Math.min(100, percentage));
555
+ const computedValue = min + rangeSize * (clampedPercentage / 100);
482
556
  // Update the appropriate value based on thumb type
483
- if (this.thumb() === 'low') {
484
- this.state().setLowValue(value);
557
+ if (thumb() === 'low') {
558
+ rangeSlider().setLowValue(computedValue);
485
559
  }
486
560
  else {
487
- this.state().setHighValue(value);
561
+ rangeSlider().setHighValue(computedValue);
488
562
  }
489
563
  }
490
- /**
491
- * Handle keyboard events.
492
- * @param event
493
- */
494
- handleKeydown(event) {
564
+ function handleKeydown(event) {
495
565
  const multiplier = event.shiftKey ? 10 : 1;
496
- const currentValue = this.value();
497
- const step = this.state().step() * multiplier;
566
+ const currentValue = value();
567
+ const step = rangeSlider().step() * multiplier;
498
568
  // determine the document direction
499
- const isRTL = getComputedStyle(this.elementRef.nativeElement).direction === 'rtl';
569
+ const isRTL = getComputedStyle(element.nativeElement).direction === 'rtl';
500
570
  let newValue;
501
571
  switch (event.key) {
502
572
  case 'ArrowLeft':
503
573
  newValue = isRTL
504
- ? Math.min(currentValue - step, this.state().max())
505
- : Math.max(currentValue - step, this.state().min());
574
+ ? Math.min(currentValue - step, rangeSlider().max())
575
+ : Math.max(currentValue - step, rangeSlider().min());
506
576
  break;
507
577
  case 'ArrowDown':
508
- newValue = Math.max(currentValue - step, this.state().min());
578
+ newValue = Math.max(currentValue - step, rangeSlider().min());
509
579
  break;
510
580
  case 'ArrowRight':
511
581
  newValue = isRTL
512
- ? Math.max(currentValue + step, this.state().min())
513
- : Math.min(currentValue + step, this.state().max());
582
+ ? Math.max(currentValue + step, rangeSlider().min())
583
+ : Math.min(currentValue + step, rangeSlider().max());
514
584
  break;
515
585
  case 'ArrowUp':
516
- newValue = Math.min(currentValue + step, this.state().max());
586
+ newValue = Math.min(currentValue + step, rangeSlider().max());
517
587
  break;
518
588
  case 'Home':
519
- newValue = isRTL ? this.state().max() : this.state().min();
589
+ newValue = isRTL ? rangeSlider().max() : rangeSlider().min();
520
590
  break;
521
591
  case 'End':
522
- newValue = isRTL ? this.state().min() : this.state().max();
592
+ newValue = isRTL ? rangeSlider().min() : rangeSlider().max();
523
593
  break;
524
594
  default:
525
595
  return;
526
596
  }
527
597
  // Update the appropriate value based on thumb type
528
- if (this.thumb() === 'low') {
529
- this.state().setLowValue(newValue);
598
+ if (thumb() === 'low') {
599
+ rangeSlider().setLowValue(newValue);
530
600
  }
531
601
  else {
532
- this.state().setHighValue(newValue);
602
+ rangeSlider().setHighValue(newValue);
533
603
  }
534
604
  event.preventDefault();
535
605
  }
606
+ // Event listeners
607
+ listener(element, 'pointerdown', handlePointerDown);
608
+ listener(document, 'pointerup', handlePointerUp);
609
+ listener(document, 'pointermove', handlePointerMove);
610
+ listener(element, 'keydown', handleKeydown);
611
+ // Register thumb with parent
612
+ rangeSlider().addThumb(element);
613
+ // Cleanup on destroy
614
+ onDestroy(() => rangeSlider().removeThumb(element));
615
+ return {
616
+ thumb,
617
+ value,
618
+ percentage,
619
+ };
620
+ });
621
+
622
+ /**
623
+ * Apply the `ngpRangeSliderThumb` directive to an element that represents a thumb of the range slider.
624
+ * Each thumb can be configured to control either the 'low' or 'high' value.
625
+ */
626
+ class NgpRangeSliderThumb {
627
+ constructor() {
628
+ ngpRangeSliderThumb({});
629
+ }
536
630
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpRangeSliderThumb, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
537
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgpRangeSliderThumb, isStandalone: true, selector: "[ngpRangeSliderThumb]", host: { attributes: { "role": "slider" }, listeners: { "pointerdown": "handlePointerDown($event)", "document:pointerup": "handlePointerUp()", "document:pointermove": "handlePointerMove($event)", "keydown": "handleKeydown($event)" }, properties: { "attr.aria-valuemin": "state().min()", "attr.aria-valuemax": "state().max()", "attr.aria-valuenow": "value()", "attr.aria-orientation": "state().orientation()", "tabindex": "state().disabled() ? -1 : 0", "attr.data-orientation": "state().orientation()", "attr.data-disabled": "state().disabled() ? \"\" : null", "attr.data-thumb": "thumb()", "style.inset-inline-start.%": "state().orientation() === \"horizontal\" ? percentage() : undefined", "style.inset-block-start.%": "state().orientation() === \"vertical\" ? percentage() : undefined" } }, exportAs: ["ngpRangeSliderThumb"], ngImport: i0 }); }
631
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgpRangeSliderThumb, isStandalone: true, selector: "[ngpRangeSliderThumb]", exportAs: ["ngpRangeSliderThumb"], ngImport: i0 }); }
538
632
  }
539
633
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpRangeSliderThumb, decorators: [{
540
634
  type: Directive,
541
635
  args: [{
542
636
  selector: '[ngpRangeSliderThumb]',
543
637
  exportAs: 'ngpRangeSliderThumb',
544
- host: {
545
- role: 'slider',
546
- '[attr.aria-valuemin]': 'state().min()',
547
- '[attr.aria-valuemax]': 'state().max()',
548
- '[attr.aria-valuenow]': 'value()',
549
- '[attr.aria-orientation]': 'state().orientation()',
550
- '[tabindex]': 'state().disabled() ? -1 : 0',
551
- '[attr.data-orientation]': 'state().orientation()',
552
- '[attr.data-disabled]': 'state().disabled() ? "" : null',
553
- '[attr.data-thumb]': 'thumb()',
554
- '[style.inset-inline-start.%]': 'state().orientation() === "horizontal" ? percentage() : undefined',
555
- '[style.inset-block-start.%]': 'state().orientation() === "vertical" ? percentage() : undefined',
556
- },
557
638
  }]
558
- }], ctorParameters: () => [], propDecorators: { handlePointerDown: [{
559
- type: HostListener,
560
- args: ['pointerdown', ['$event']]
561
- }], handlePointerUp: [{
562
- type: HostListener,
563
- args: ['document:pointerup']
564
- }], handlePointerMove: [{
565
- type: HostListener,
566
- args: ['document:pointermove', ['$event']]
567
- }], handleKeydown: [{
568
- type: HostListener,
569
- args: ['keydown', ['$event']]
570
- }] } });
639
+ }], ctorParameters: () => [] });
571
640
 
572
- /**
573
- * Apply the `ngpRangeSliderTrack` directive to an element that represents the track of the range slider.
574
- */
575
- class NgpRangeSliderTrack {
576
- constructor() {
577
- /**
578
- * Access the range slider state.
579
- */
580
- this.rangeSliderState = injectRangeSliderState();
581
- /**
582
- * The element that represents the slider track.
583
- */
584
- this.element = injectElementRef();
585
- this.rangeSliderState().track.set(this);
586
- }
587
- /**
588
- * When the slider track is clicked, update the closest thumb value.
589
- * @param event The click event.
590
- */
591
- handlePointerDown(event) {
592
- if (this.rangeSliderState().disabled()) {
641
+ const [NgpRangeSliderTrackStateToken, ngpRangeSliderTrack, injectRangeSliderTrackState, provideRangeSliderTrackState,] = createPrimitive('NgpRangeSliderTrack', ({}) => {
642
+ const element = injectElementRef();
643
+ const rangeSlider = injectRangeSliderState();
644
+ // Host bindings
645
+ dataBinding(element, 'data-orientation', () => rangeSlider().orientation());
646
+ dataBinding(element, 'data-disabled', () => rangeSlider().disabled());
647
+ function handlePointerDown(event) {
648
+ if (rangeSlider().disabled()) {
593
649
  return;
594
650
  }
595
651
  // get the position the click occurred within the slider track
596
- const position = this.rangeSliderState().orientation() === 'horizontal' ? event.clientX : event.clientY;
597
- const rect = this.element.nativeElement.getBoundingClientRect();
598
- const percentage = (position - (this.rangeSliderState().orientation() === 'horizontal' ? rect.left : rect.top)) /
599
- (this.rangeSliderState().orientation() === 'horizontal' ? rect.width : rect.height);
652
+ const isHorizontal = rangeSlider().orientation() === 'horizontal';
653
+ const max = rangeSlider().max();
654
+ const min = rangeSlider().min();
655
+ const position = isHorizontal ? event.clientX : event.clientY;
656
+ const rect = element.nativeElement.getBoundingClientRect();
657
+ const start = isHorizontal ? rect.left : rect.top;
658
+ const size = isHorizontal ? rect.width : rect.height;
659
+ const percentage = (position - start) / size;
600
660
  // calculate the value based on the position
601
- const value = this.rangeSliderState().min() +
602
- (this.rangeSliderState().max() - this.rangeSliderState().min()) * percentage;
661
+ const value = min + (max - min) * percentage;
603
662
  // determine which thumb to move based on proximity
604
- const closestThumb = this.rangeSliderState().getClosestThumb(percentage * 100);
663
+ const closestThumb = rangeSlider().getClosestThumb(percentage * 100);
605
664
  if (closestThumb === 'low') {
606
- this.rangeSliderState().setLowValue(value);
665
+ rangeSlider().setLowValue(value);
607
666
  }
608
667
  else {
609
- this.rangeSliderState().setHighValue(value);
668
+ rangeSlider().setHighValue(value);
610
669
  }
611
670
  }
671
+ // Event listener
672
+ listener(element, 'pointerdown', handlePointerDown);
673
+ // Register track with parent
674
+ rangeSlider().setTrack(element);
675
+ });
676
+
677
+ /**
678
+ * Apply the `ngpRangeSliderTrack` directive to an element that represents the track of the range slider.
679
+ */
680
+ class NgpRangeSliderTrack {
681
+ constructor() {
682
+ ngpRangeSliderTrack({});
683
+ }
612
684
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpRangeSliderTrack, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
613
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgpRangeSliderTrack, isStandalone: true, selector: "[ngpRangeSliderTrack]", host: { listeners: { "pointerdown": "handlePointerDown($event)" }, properties: { "attr.data-orientation": "rangeSliderState().orientation()", "attr.data-disabled": "rangeSliderState().disabled() ? \"\" : null" } }, exportAs: ["ngpRangeSliderTrack"], ngImport: i0 }); }
685
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgpRangeSliderTrack, isStandalone: true, selector: "[ngpRangeSliderTrack]", exportAs: ["ngpRangeSliderTrack"], ngImport: i0 }); }
614
686
  }
615
687
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpRangeSliderTrack, decorators: [{
616
688
  type: Directive,
617
689
  args: [{
618
690
  selector: '[ngpRangeSliderTrack]',
619
691
  exportAs: 'ngpRangeSliderTrack',
620
- host: {
621
- '[attr.data-orientation]': 'rangeSliderState().orientation()',
622
- '[attr.data-disabled]': 'rangeSliderState().disabled() ? "" : null',
623
- },
624
692
  }]
625
- }], ctorParameters: () => [], propDecorators: { handlePointerDown: [{
626
- type: HostListener,
627
- args: ['pointerdown', ['$event']]
628
- }] } });
693
+ }], ctorParameters: () => [] });
629
694
 
630
695
  /**
631
696
  * Apply the `ngpRangeSlider` directive to an element that represents the range slider and contains the track, range, and thumbs.
@@ -703,88 +768,23 @@ class NgpRangeSlider {
703
768
  transform: booleanAttribute,
704
769
  }]));
705
770
  /**
706
- * Access the slider track.
707
- * @internal
771
+ * The state of the range slider.
708
772
  */
709
- this.track = signal(undefined, ...(ngDevMode ? [{ debugName: "track" }] : []));
710
- /**
711
- * The thumbs of the range slider.
712
- * @internal
713
- */
714
- this.thumbs = signal([], ...(ngDevMode ? [{ debugName: "thumbs" }] : []));
715
- /**
716
- * The low value as a percentage based on the min and max values.
717
- * @internal
718
- */
719
- this.lowPercentage = computed(() => ((this.state.low() - this.state.min()) / (this.state.max() - this.state.min())) * 100, ...(ngDevMode ? [{ debugName: "lowPercentage" }] : []));
720
- /**
721
- * The high value as a percentage based on the min and max values.
722
- * @internal
723
- */
724
- this.highPercentage = computed(() => ((this.state.high() - this.state.min()) / (this.state.max() - this.state.min())) * 100, ...(ngDevMode ? [{ debugName: "highPercentage" }] : []));
725
- /**
726
- * The range between low and high values as a percentage.
727
- * @internal
728
- */
729
- this.rangePercentage = computed(() => this.highPercentage() - this.lowPercentage(), ...(ngDevMode ? [{ debugName: "rangePercentage" }] : []));
730
- /**
731
- * The state of the range slider. We use this for the range slider state rather than relying on the inputs.
732
- * @internal
733
- */
734
- this.state = rangeSliderState(this);
735
- ngpFormControl({ id: this.state.id, disabled: this.state.disabled });
736
- }
737
- /**
738
- * Updates the low value, ensuring it doesn't exceed the high value.
739
- * @param value The new low value
740
- * @internal
741
- */
742
- setLowValue(value) {
743
- const clampedValue = Math.max(this.state.min(), Math.min(value, this.state.high()));
744
- this.state.low.set(clampedValue);
745
- this.lowChange.emit(clampedValue);
746
- }
747
- /**
748
- * Updates the high value, ensuring it doesn't go below the low value.
749
- * @param value The new high value
750
- * @internal
751
- */
752
- setHighValue(value) {
753
- const clampedValue = Math.min(this.state.max(), Math.max(value, this.state.low()));
754
- this.state.high.set(clampedValue);
755
- this.highChange.emit(clampedValue);
756
- }
757
- /**
758
- * Determines which thumb should be moved based on the position clicked.
759
- * @param percentage The percentage position of the click
760
- * @returns 'low' or 'high' indicating which thumb should move
761
- *
762
- * @internal
763
- */
764
- getClosestThumb(percentage) {
765
- const value = this.state.min() + (this.state.max() - this.state.min()) * (percentage / 100);
766
- const distanceToLow = Math.abs(value - this.state.low());
767
- const distanceToHigh = Math.abs(value - this.state.high());
768
- return distanceToLow <= distanceToHigh ? 'low' : 'high';
769
- }
770
- /**
771
- * Updates the thumbs array when a new thumb is added.
772
- * @param thumb The new thumb to add
773
- * @internal
774
- */
775
- addThumb(thumb) {
776
- this.thumbs.update(thumbs => [...thumbs, thumb]);
777
- }
778
- /**
779
- * Removes a thumb from the thumbs array.
780
- * @param thumb The thumb to remove
781
- * @internal
782
- */
783
- removeThumb(thumb) {
784
- this.thumbs.update(thumbs => thumbs.filter(t => t !== thumb));
773
+ this.state = ngpRangeSlider({
774
+ id: this.id,
775
+ low: this.low,
776
+ high: this.high,
777
+ min: this.min,
778
+ max: this.max,
779
+ step: this.step,
780
+ orientation: this.orientation,
781
+ disabled: this.disabled,
782
+ onLowChange: value => this.lowChange.emit(value),
783
+ onHighChange: value => this.highChange.emit(value),
784
+ });
785
785
  }
786
786
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpRangeSlider, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
787
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpRangeSlider, isStandalone: true, selector: "[ngpRangeSlider]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, low: { classPropertyName: "low", publicName: "ngpRangeSliderLow", isSignal: true, isRequired: false, transformFunction: null }, high: { classPropertyName: "high", publicName: "ngpRangeSliderHigh", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "ngpRangeSliderMin", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "ngpRangeSliderMax", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "ngpRangeSliderStep", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "ngpRangeSliderOrientation", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpRangeSliderDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { lowChange: "ngpRangeSliderLowChange", highChange: "ngpRangeSliderHighChange" }, host: { properties: { "id": "id()", "attr.data-orientation": "state.orientation()" } }, providers: [provideRangeSliderState()], exportAs: ["ngpRangeSlider"], ngImport: i0 }); }
787
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpRangeSlider, isStandalone: true, selector: "[ngpRangeSlider]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, low: { classPropertyName: "low", publicName: "ngpRangeSliderLow", isSignal: true, isRequired: false, transformFunction: null }, high: { classPropertyName: "high", publicName: "ngpRangeSliderHigh", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "ngpRangeSliderMin", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "ngpRangeSliderMax", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "ngpRangeSliderStep", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "ngpRangeSliderOrientation", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpRangeSliderDisabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { lowChange: "ngpRangeSliderLowChange", highChange: "ngpRangeSliderHighChange" }, providers: [provideRangeSliderState()], exportAs: ["ngpRangeSlider"], ngImport: i0 }); }
788
788
  }
789
789
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpRangeSlider, decorators: [{
790
790
  type: Directive,
@@ -792,16 +792,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
792
792
  selector: '[ngpRangeSlider]',
793
793
  exportAs: 'ngpRangeSlider',
794
794
  providers: [provideRangeSliderState()],
795
- host: {
796
- '[id]': 'id()',
797
- '[attr.data-orientation]': 'state.orientation()',
798
- },
799
795
  }]
800
- }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], low: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderLow", required: false }] }], lowChange: [{ type: i0.Output, args: ["ngpRangeSliderLowChange"] }], high: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderHigh", required: false }] }], highChange: [{ type: i0.Output, args: ["ngpRangeSliderHighChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderMin", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderMax", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderStep", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderOrientation", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderDisabled", required: false }] }] } });
796
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], low: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderLow", required: false }] }], lowChange: [{ type: i0.Output, args: ["ngpRangeSliderLowChange"] }], high: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderHigh", required: false }] }], highChange: [{ type: i0.Output, args: ["ngpRangeSliderHighChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderMin", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderMax", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderStep", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderOrientation", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpRangeSliderDisabled", required: false }] }] } });
801
797
 
802
798
  /**
803
799
  * Generated bundle index. Do not edit.
804
800
  */
805
801
 
806
- export { NgpRangeSlider, NgpRangeSliderRange, NgpRangeSliderThumb, NgpRangeSliderTrack, NgpSlider, NgpSliderRange, NgpSliderThumb, NgpSliderTrack, injectRangeSliderState, injectSliderRangeState, injectSliderState, injectSliderThumbState, injectSliderTrackState, ngpSlider, ngpSliderRange, ngpSliderThumb, ngpSliderTrack, provideRangeSliderState, provideSliderRangeState, provideSliderState, provideSliderThumbState, provideSliderTrackState };
802
+ export { NgpRangeSlider, NgpRangeSliderRange, NgpRangeSliderThumb, NgpRangeSliderTrack, NgpSlider, NgpSliderRange, NgpSliderThumb, NgpSliderTrack, injectRangeSliderRangeState, injectRangeSliderState, injectRangeSliderThumbState, injectRangeSliderTrackState, injectSliderRangeState, injectSliderState, injectSliderThumbState, injectSliderTrackState, ngpRangeSlider, ngpRangeSliderRange, ngpRangeSliderThumb, ngpRangeSliderTrack, ngpSlider, ngpSliderRange, ngpSliderThumb, ngpSliderTrack, provideRangeSliderRangeState, provideRangeSliderState, provideRangeSliderThumbState, provideRangeSliderTrackState, provideSliderRangeState, provideSliderState, provideSliderThumbState, provideSliderTrackState };
807
803
  //# sourceMappingURL=ng-primitives-slider.mjs.map