@ship-ui/core 0.19.3 → 0.19.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, computed, ElementRef, Renderer2, input, ChangeDetectionStrategy, Component, viewChild, effect, HostListener, NgModule, signal, Injectable, DOCUMENT, model, output, ApplicationRef, OutputEmitterRef, TemplateRef, createComponent, isSignal, DestroyRef, PLATFORM_ID, ViewChild, booleanAttribute, Directive, untracked, contentChild, contentChildren, afterNextRender, Injector, HostBinding, runInInjectionContext, ChangeDetectorRef, viewChildren, ViewContainerRef, EnvironmentInjector } from '@angular/core';
2
+ import { InjectionToken, inject, computed, ElementRef, Renderer2, input, ChangeDetectionStrategy, Component, viewChild, effect, HostListener, NgModule, signal, Injectable, DOCUMENT, model, output, ApplicationRef, OutputEmitterRef, TemplateRef, createComponent, isSignal, DestroyRef, PLATFORM_ID, ViewChild, booleanAttribute, Directive, untracked, contentChild, afterNextRender, Injector, HostBinding, runInInjectionContext, ChangeDetectorRef, viewChildren, ViewContainerRef, EnvironmentInjector } from '@angular/core';
3
3
  import { isPlatformBrowser, JsonPipe, DatePipe, isPlatformServer, NgTemplateOutlet } from '@angular/common';
4
- import { NgModel } from '@angular/forms';
4
+ import { NgControl } from '@angular/forms';
5
5
  import { isObservable, firstValueFrom } from 'rxjs';
6
6
 
7
7
  const defaultThemeColors = {
@@ -100,7 +100,7 @@ class ShipIcon {
100
100
  }
101
101
  }
102
102
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipIcon, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
103
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.6", type: ShipIcon, isStandalone: true, selector: "sh-icon", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
103
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.6", type: ShipIcon, isStandalone: true, selector: "sh-icon", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()", "attr.aria-hidden": "\"true\"" } }, ngImport: i0, template: `
104
104
  <ng-content />
105
105
  `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
106
106
  }
@@ -116,6 +116,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
116
116
  changeDetection: ChangeDetectionStrategy.OnPush,
117
117
  host: {
118
118
  '[class]': 'hostClasses()',
119
+ '[attr.aria-hidden]': '"true"',
119
120
  },
120
121
  }]
121
122
  }], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
@@ -1942,12 +1943,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
1942
1943
  }] } });
1943
1944
 
1944
1945
  class ShipSelectionGroup {
1945
- constructor(itemSelector, activeClass) {
1946
+ constructor(itemSelector, activeClass, options) {
1946
1947
  this.itemSelector = itemSelector;
1947
1948
  this.activeClass = activeClass;
1949
+ this.options = options;
1948
1950
  this.hostElement = inject((ElementRef)).nativeElement;
1949
1951
  this.value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
1950
1952
  this.closable = input(false, { ...(ngDevMode ? { debugName: "closable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1953
+ this.manualActivation = input(false, { ...(ngDevMode ? { debugName: "manualActivation" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
1954
+ if (this.options?.hostRole) {
1955
+ this.hostElement.setAttribute('role', this.options.hostRole);
1956
+ }
1951
1957
  this.items = contentProjectionSignal(this.itemSelector, {
1952
1958
  childList: true,
1953
1959
  subtree: true,
@@ -1956,7 +1962,20 @@ class ShipSelectionGroup {
1956
1962
  effect(() => {
1957
1963
  const selectedValue = this.value();
1958
1964
  const activeClass = this.activeClass;
1959
- this.items().forEach((item) => {
1965
+ const items = this.items();
1966
+ let hasSelection = false;
1967
+ items.forEach((item) => {
1968
+ const itemValue = item.getAttribute('value');
1969
+ if (itemValue === null && !item.hasAttribute('value'))
1970
+ return;
1971
+ if (itemValue === String(selectedValue) || (itemValue === '' && (selectedValue === null || selectedValue === ''))) {
1972
+ hasSelection = true;
1973
+ }
1974
+ });
1975
+ items.forEach((item) => {
1976
+ if (this.options?.itemRole && !item.hasAttribute('role')) {
1977
+ item.setAttribute('role', this.options.itemRole);
1978
+ }
1960
1979
  const itemValue = item.getAttribute('value');
1961
1980
  // If the item doesn't have a value attribute, it's not participate in the selection
1962
1981
  if (itemValue === null && !item.hasAttribute('value'))
@@ -1964,9 +1983,18 @@ class ShipSelectionGroup {
1964
1983
  // Exact match or handle empty string matching properly
1965
1984
  if (itemValue === String(selectedValue) || (itemValue === '' && (selectedValue === null || selectedValue === ''))) {
1966
1985
  item.classList.add(activeClass);
1986
+ item.setAttribute('aria-selected', 'true');
1987
+ item.setAttribute('tabindex', '0');
1967
1988
  }
1968
1989
  else {
1969
1990
  item.classList.remove(activeClass);
1991
+ item.setAttribute('aria-selected', 'false');
1992
+ if (hasSelection) {
1993
+ item.setAttribute('tabindex', '-1');
1994
+ }
1995
+ else {
1996
+ item.removeAttribute('tabindex');
1997
+ }
1970
1998
  }
1971
1999
  });
1972
2000
  });
@@ -1989,19 +2017,41 @@ class ShipSelectionGroup {
1989
2017
  }
1990
2018
  }
1991
2019
  onKeyDown(event) {
2020
+ const targetEl = event.target;
2021
+ if (event.key === 'Enter' || event.key === ' ') {
2022
+ const item = targetEl?.closest?.(this.itemSelector);
2023
+ if (item && this.hostElement.contains(item) && item.hasAttribute('value')) {
2024
+ // Only prevent default for space to avoid scrolling, let enter naturally click if it's a link/button
2025
+ if (event.key === ' ')
2026
+ event.preventDefault();
2027
+ const value = item.getAttribute('value');
2028
+ if (this.closable() && String(this.value()) === String(value)) {
2029
+ this.value.set(null);
2030
+ }
2031
+ else {
2032
+ this.value.set(value);
2033
+ }
2034
+ }
2035
+ return;
2036
+ }
1992
2037
  const items = this.items().filter(item => item.hasAttribute('value'));
1993
2038
  if (!items.length)
1994
2039
  return;
1995
- const currentIndex = items.findIndex((item) => item.classList.contains(this.activeClass));
1996
- let nextIndex = currentIndex;
2040
+ let activeIndex = items.findIndex((item) => item === document.activeElement || item.contains(document.activeElement));
2041
+ if (activeIndex === -1) {
2042
+ activeIndex = items.findIndex((item) => item.classList.contains(this.activeClass));
2043
+ }
2044
+ if (activeIndex === -1)
2045
+ activeIndex = 0;
2046
+ let nextIndex = activeIndex;
1997
2047
  switch (event.key) {
1998
2048
  case 'ArrowRight':
1999
2049
  case 'ArrowDown':
2000
- nextIndex = currentIndex >= items.length - 1 ? 0 : currentIndex + 1;
2050
+ nextIndex = activeIndex >= items.length - 1 ? 0 : activeIndex + 1;
2001
2051
  break;
2002
2052
  case 'ArrowLeft':
2003
2053
  case 'ArrowUp':
2004
- nextIndex = currentIndex <= 0 ? items.length - 1 : currentIndex - 1;
2054
+ nextIndex = activeIndex <= 0 ? items.length - 1 : activeIndex - 1;
2005
2055
  break;
2006
2056
  default:
2007
2057
  return; // Let other keys propagate natively
@@ -2009,17 +2059,19 @@ class ShipSelectionGroup {
2009
2059
  event.preventDefault();
2010
2060
  const nextItem = items[nextIndex];
2011
2061
  if (nextItem) {
2012
- const value = nextItem.getAttribute('value');
2013
- this.value.set(value);
2062
+ if (!this.manualActivation()) {
2063
+ const value = nextItem.getAttribute('value');
2064
+ this.value.set(value);
2065
+ }
2014
2066
  nextItem.focus();
2015
2067
  }
2016
2068
  }
2017
2069
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipSelectionGroup, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive }); }
2018
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.6", type: ShipSelectionGroup, isStandalone: true, inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { listeners: { "click": "onClick($event.target)", "keydown": "onKeyDown($event)" } }, ngImport: i0 }); }
2070
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.6", type: ShipSelectionGroup, isStandalone: true, inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, manualActivation: { classPropertyName: "manualActivation", publicName: "manualActivation", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { listeners: { "click": "onClick($event.target)", "keydown": "onKeyDown($event)" } }, ngImport: i0 }); }
2019
2071
  }
2020
2072
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipSelectionGroup, decorators: [{
2021
2073
  type: Directive
2022
- }], ctorParameters: () => [{ type: undefined }, { type: undefined }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], onClick: [{
2074
+ }], ctorParameters: () => [{ type: undefined }, { type: undefined }, { type: undefined }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], manualActivation: [{ type: i0.Input, args: [{ isSignal: true, alias: "manualActivation", required: false }] }], onClick: [{
2023
2075
  type: HostListener,
2024
2076
  args: ['click', ['$event.target']]
2025
2077
  }], onKeyDown: [{
@@ -2029,7 +2081,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
2029
2081
 
2030
2082
  class ShipButtonGroup extends ShipSelectionGroup {
2031
2083
  constructor() {
2032
- super('button', 'active');
2084
+ super('button', 'active', { hostRole: 'group' });
2033
2085
  this.id = '--' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 12);
2034
2086
  this.color = input(null, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
2035
2087
  this.variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -2158,7 +2210,7 @@ class ShipCheckbox {
2158
2210
  event.preventDefault();
2159
2211
  }
2160
2212
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2161
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipCheckbox, isStandalone: true, selector: "sh-checkbox", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, noInternalInput: { classPropertyName: "noInternalInput", publicName: "noInternalInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, host: { listeners: { "keydown.enter": "onEnter($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() ? \"\" : null" } }, viewQueries: [{ propertyName: "internalInput", first: true, predicate: ["internalInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
2213
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipCheckbox, isStandalone: true, selector: "sh-checkbox", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, noInternalInput: { classPropertyName: "noInternalInput", publicName: "noInternalInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, host: { listeners: { "keydown.enter": "onEnter($event)", "keydown.space": "onEnter($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() ? \"\" : null", "attr.role": "noInternalInput() ? \"checkbox\" : null", "attr.aria-checked": "noInternalInput() ? checked() : null", "attr.tabindex": "noInternalInput() ? (disabled() ? \"-1\" : \"0\") : null" } }, viewQueries: [{ propertyName: "internalInput", first: true, predicate: ["internalInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
2162
2214
  <div class="box sh-sheet" [class]="currentClassList()">
2163
2215
  <sh-icon class="inherit default-indicator">check-bold</sh-icon>
2164
2216
  <sh-icon class="inherit indeterminate-indicator">minus-bold</sh-icon>
@@ -2208,11 +2260,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
2208
2260
  host: {
2209
2261
  '[class]': 'hostClasses()',
2210
2262
  '[attr.disabled]': 'disabled() ? "" : null',
2263
+ '[attr.role]': 'noInternalInput() ? "checkbox" : null',
2264
+ '[attr.aria-checked]': 'noInternalInput() ? checked() : null',
2265
+ '[attr.tabindex]': 'noInternalInput() ? (disabled() ? "-1" : "0") : null',
2211
2266
  },
2212
2267
  }]
2213
2268
  }], propDecorators: { internalInput: [{ type: i0.ViewChild, args: ['internalInput', { isSignal: true }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], noInternalInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "noInternalInput", required: false }] }], onEnter: [{
2214
2269
  type: HostListener,
2215
2270
  args: ['keydown.enter', ['$event']]
2271
+ }, {
2272
+ type: HostListener,
2273
+ args: ['keydown.space', ['$event']]
2216
2274
  }] } });
2217
2275
 
2218
2276
  class ShipChip {
@@ -2956,8 +3014,8 @@ class ShipPopover {
2956
3014
  this.#originalOverflow = null;
2957
3015
  this.openEffect = effect(() => {
2958
3016
  const open = this.isOpen();
3017
+ const popoverEl = this.popoverRef()?.nativeElement;
2959
3018
  queueMicrotask(() => {
2960
- const popoverEl = this.popoverRef()?.nativeElement;
2961
3019
  if (!popoverEl) {
2962
3020
  this.openAbort?.abort();
2963
3021
  this.openAbort = null;
@@ -3213,12 +3271,15 @@ class ShipFormFieldPopover {
3213
3271
  });
3214
3272
  }
3215
3273
  #selfRef;
3216
- onClick() {
3217
- if (this.#selfRef.nativeElement.querySelector('input')) {
3218
- this.#selfRef.nativeElement.querySelector('input').focus();
3219
- }
3220
- if (this.#selfRef.nativeElement.querySelector('textarea')) {
3221
- this.#selfRef.nativeElement.querySelector('textarea').focus();
3274
+ onClick(event) {
3275
+ const target = event.target;
3276
+ if (target.closest('.input-wrap')) {
3277
+ if (this.#selfRef.nativeElement.querySelector('input')) {
3278
+ this.#selfRef.nativeElement.querySelector('input').focus();
3279
+ }
3280
+ if (this.#selfRef.nativeElement.querySelector('textarea')) {
3281
+ this.#selfRef.nativeElement.querySelector('textarea').focus();
3282
+ }
3222
3283
  }
3223
3284
  }
3224
3285
  close() {
@@ -3250,7 +3311,7 @@ class ShipFormFieldPopover {
3250
3311
  }
3251
3312
  }
3252
3313
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipFormFieldPopover, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3253
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.6", type: ShipFormFieldPopover, isStandalone: true, selector: "sh-form-field-popover", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", closed: "closed" }, host: { listeners: { "click": "onClick()" }, properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
3314
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.6", type: ShipFormFieldPopover, isStandalone: true, selector: "sh-form-field-popover", inputs: { isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpen: "isOpenChange", closed: "closed" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
3254
3315
  <ng-content select="label"></ng-content>
3255
3316
 
3256
3317
  <sh-popover
@@ -3261,7 +3322,7 @@ class ShipFormFieldPopover {
3261
3322
  closeOnButton: false,
3262
3323
  closeOnEsc: true,
3263
3324
  }">
3264
- <div trigger class="input-wrap">
3325
+ <div trigger class="input-wrap" [class.is-open]="isOpen()">
3265
3326
  <div class="prefix">
3266
3327
  <ng-content select="[prefix]"></ng-content>
3267
3328
  <ng-content select="[textPrefix]"></ng-content>
@@ -3307,7 +3368,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
3307
3368
  closeOnButton: false,
3308
3369
  closeOnEsc: true,
3309
3370
  }">
3310
- <div trigger class="input-wrap">
3371
+ <div trigger class="input-wrap" [class.is-open]="isOpen()">
3311
3372
  <div class="prefix">
3312
3373
  <ng-content select="[prefix]"></ng-content>
3313
3374
  <ng-content select="[textPrefix]"></ng-content>
@@ -3343,7 +3404,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
3343
3404
  }]
3344
3405
  }], propDecorators: { isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], onClick: [{
3345
3406
  type: HostListener,
3346
- args: ['click']
3407
+ args: ['click', ['$event']]
3347
3408
  }] } });
3348
3409
 
3349
3410
  class ShipColorPickerInput {
@@ -3601,15 +3662,14 @@ class ShipColorPickerInput {
3601
3662
  }
3602
3663
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipColorPickerInput, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3603
3664
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipColorPickerInput, isStandalone: true, selector: "sh-color-picker-input", inputs: { renderingType: { classPropertyName: "renderingType", publicName: "renderingType", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null }, showEyeDropper: { classPropertyName: "showEyeDropper", publicName: "showEyeDropper", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", isOpen: "isOpenChange" }, ngImport: i0, template: `
3604
- <sh-form-field-popover
3605
- (closed)="close()"
3606
- [(isOpen)]="isOpen"
3665
+ <sh-form-field-popover
3666
+ (closed)="close()"
3667
+ [(isOpen)]="isOpen"
3607
3668
  [class]="currentClass()"
3608
3669
  [variant]="variant()"
3609
3670
  [size]="size()"
3610
3671
  [color]="color()"
3611
- [readonly]="readonly()"
3612
- >
3672
+ [readonly]="readonly()">
3613
3673
  <ng-content select="label" ngProjectAs="label" />
3614
3674
 
3615
3675
  <ng-content select="[prefix]" ngProjectAs="[prefix]" />
@@ -3667,15 +3727,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
3667
3727
  selector: 'sh-color-picker-input',
3668
3728
  imports: [ShipFormFieldPopover, ShipColorPicker, ShipIcon, ShipButton],
3669
3729
  template: `
3670
- <sh-form-field-popover
3671
- (closed)="close()"
3672
- [(isOpen)]="isOpen"
3730
+ <sh-form-field-popover
3731
+ (closed)="close()"
3732
+ [(isOpen)]="isOpen"
3673
3733
  [class]="currentClass()"
3674
3734
  [variant]="variant()"
3675
3735
  [size]="size()"
3676
3736
  [color]="color()"
3677
- [readonly]="readonly()"
3678
- >
3737
+ [readonly]="readonly()">
3679
3738
  <ng-content select="label" ngProjectAs="label" />
3680
3739
 
3681
3740
  <ng-content select="[prefix]" ngProjectAs="[prefix]" />
@@ -3736,8 +3795,10 @@ class ShipDatepicker {
3736
3795
  this.date = model(null, ...(ngDevMode ? [{ debugName: "date" }] : /* istanbul ignore next */ []));
3737
3796
  this.endDate = model(null, ...(ngDevMode ? [{ debugName: "endDate" }] : /* istanbul ignore next */ []));
3738
3797
  this.asRange = input(false, ...(ngDevMode ? [{ debugName: "asRange" }] : /* istanbul ignore next */ []));
3798
+ this.activeRangeSelection = input(null, ...(ngDevMode ? [{ debugName: "activeRangeSelection" }] : /* istanbul ignore next */ []));
3739
3799
  this.monthsToShow = input(1, ...(ngDevMode ? [{ debugName: "monthsToShow" }] : /* istanbul ignore next */ []));
3740
3800
  this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
3801
+ this.tabbedOut = output();
3741
3802
  this.startOfWeek = input(1, ...(ngDevMode ? [{ debugName: "startOfWeek" }] : /* istanbul ignore next */ []));
3742
3803
  this.weekdayLabels = input(['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], ...(ngDevMode ? [{ debugName: "weekdayLabels" }] : /* istanbul ignore next */ []));
3743
3804
  this.daysRef = viewChild('daysRef', ...(ngDevMode ? [{ debugName: "daysRef" }] : /* istanbul ignore next */ []));
@@ -3761,6 +3822,8 @@ class ShipDatepicker {
3761
3822
  return;
3762
3823
  this.#setDateAsCurrent();
3763
3824
  }, ...(ngDevMode ? [{ debugName: "#newDateEffect" }] : /* istanbul ignore next */ []));
3825
+ this.focusedDate = signal(null, ...(ngDevMode ? [{ debugName: "focusedDate" }] : /* istanbul ignore next */ []));
3826
+ this.#selfRef = inject(ElementRef);
3764
3827
  }
3765
3828
  #INIT_DATE;
3766
3829
  getLastVisibleMonth() {
@@ -3784,8 +3847,9 @@ class ShipDatepicker {
3784
3847
  }
3785
3848
  #setDateAsCurrent() {
3786
3849
  const newDate = this.date();
3787
- if (newDate)
3850
+ if (newDate && !isNaN(newDate.getTime())) {
3788
3851
  this.currentDate.set(newDate);
3852
+ }
3789
3853
  this.#findSelectedAndCalc();
3790
3854
  }
3791
3855
  #findSelectedAndCalc() {
@@ -3837,11 +3901,20 @@ class ShipDatepicker {
3837
3901
  this.#findSelectedAndCalc();
3838
3902
  }
3839
3903
  setDate(newDate, selectedElement) {
3904
+ this.focusedDate.set(newDate);
3840
3905
  const createDateWithExistingTime = (newDate, existingDate) => {
3841
- const hours = existingDate?.getHours() ?? 0;
3842
- const minutes = existingDate?.getMinutes() ?? 0;
3843
- const seconds = existingDate?.getSeconds() ?? 0;
3844
- const milliseconds = existingDate?.getMilliseconds() ?? 0;
3906
+ let hours = 0, minutes = 0, seconds = 0, milliseconds = 0;
3907
+ if (existingDate) {
3908
+ if (typeof existingDate === 'string' || typeof existingDate === 'number') {
3909
+ existingDate = new Date(existingDate);
3910
+ }
3911
+ if (existingDate instanceof Date && !isNaN(existingDate.getTime())) {
3912
+ hours = existingDate.getHours();
3913
+ minutes = existingDate.getMinutes();
3914
+ seconds = existingDate.getSeconds();
3915
+ milliseconds = existingDate.getMilliseconds();
3916
+ }
3917
+ }
3845
3918
  return new Date(newDate.getFullYear(), newDate.getMonth(), newDate.getDate(), hours, minutes, seconds, milliseconds);
3846
3919
  };
3847
3920
  if (!this.asRange()) {
@@ -3851,22 +3924,46 @@ class ShipDatepicker {
3851
3924
  else {
3852
3925
  const startDate = this.date();
3853
3926
  const endDate = this.endDate();
3854
- const utcDate = createDateWithExistingTime(newDate, null);
3855
- if (!startDate) {
3927
+ const selectionMode = this.activeRangeSelection();
3928
+ if (selectionMode === 'start') {
3929
+ const utcDate = createDateWithExistingTime(newDate, startDate);
3856
3930
  this.date.set(utcDate);
3931
+ if (endDate && utcDate > endDate) {
3932
+ this.endDate.set(null);
3933
+ }
3857
3934
  }
3858
- else if (!endDate) {
3859
- if (utcDate < startDate) {
3860
- this.date.set(utcDate);
3935
+ else if (selectionMode === 'end') {
3936
+ if (!startDate || newDate < startDate) {
3937
+ const newStart = createDateWithExistingTime(newDate, startDate);
3938
+ this.date.set(newStart);
3861
3939
  this.endDate.set(null);
3862
3940
  }
3863
3941
  else {
3942
+ const utcDate = createDateWithExistingTime(newDate, endDate);
3864
3943
  this.endDate.set(utcDate);
3865
3944
  }
3866
3945
  }
3867
3946
  else {
3868
- this.date.set(utcDate);
3869
- this.endDate.set(null);
3947
+ if (!startDate) {
3948
+ const utcDate = createDateWithExistingTime(newDate, startDate);
3949
+ this.date.set(utcDate);
3950
+ }
3951
+ else if (!endDate) {
3952
+ if (newDate < startDate) {
3953
+ const newStart = createDateWithExistingTime(newDate, startDate);
3954
+ this.date.set(newStart);
3955
+ this.endDate.set(null);
3956
+ }
3957
+ else {
3958
+ const utcDate = createDateWithExistingTime(newDate, endDate);
3959
+ this.endDate.set(utcDate);
3960
+ }
3961
+ }
3962
+ else {
3963
+ const utcDate = createDateWithExistingTime(newDate, startDate);
3964
+ this.date.set(utcDate);
3965
+ this.endDate.set(null);
3966
+ }
3870
3967
  }
3871
3968
  }
3872
3969
  if (this.asRange())
@@ -3874,9 +3971,13 @@ class ShipDatepicker {
3874
3971
  this.setSelectedDateStylePosition(selectedElement);
3875
3972
  }
3876
3973
  isDateSelected(date) {
3877
- const startDate = this.date();
3878
- const endDate = this.endDate();
3879
- if (startDate === null)
3974
+ let startDate = this.date();
3975
+ let endDate = this.endDate();
3976
+ if (typeof startDate === 'string' || typeof startDate === 'number')
3977
+ startDate = new Date(startDate);
3978
+ if (typeof endDate === 'string' || typeof endDate === 'number')
3979
+ endDate = new Date(endDate);
3980
+ if (!startDate || !(startDate instanceof Date) || isNaN(startDate.getTime()))
3880
3981
  return null;
3881
3982
  const startOfDay = (date) => {
3882
3983
  return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
@@ -3951,10 +4052,117 @@ class ShipDatepicker {
3951
4052
  const offsetDate = this.getOffsetDate(monthOffset);
3952
4053
  return date.getMonth() === offsetDate.getMonth();
3953
4054
  }
4055
+ #selfRef;
4056
+ isSameDay(d1, d2) {
4057
+ if (!d1 || !d2)
4058
+ return false;
4059
+ return d1.getFullYear() === d2.getFullYear() &&
4060
+ d1.getMonth() === d2.getMonth() &&
4061
+ d1.getDate() === d2.getDate();
4062
+ }
4063
+ getAriaLabel(date) {
4064
+ return date.toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
4065
+ }
4066
+ getTabIndex(date) {
4067
+ const focused = this.focusedDate();
4068
+ const selected = this.date();
4069
+ const today = new Date();
4070
+ if (focused) {
4071
+ return this.isSameDay(date, focused) ? 0 : -1;
4072
+ }
4073
+ if (selected) {
4074
+ return this.isSameDay(date, selected) ? 0 : -1;
4075
+ }
4076
+ return this.isSameDay(date, today) ? 0 : -1;
4077
+ }
4078
+ isDateSelectedBool(date) {
4079
+ const classes = this.isDateSelected(date);
4080
+ return classes ? classes.includes('sel') : false;
4081
+ }
4082
+ onKeydown(event, date) {
4083
+ let newDate = new Date(date);
4084
+ let handled = false;
4085
+ switch (event.key) {
4086
+ case 'ArrowRight':
4087
+ newDate.setDate(date.getDate() + 1);
4088
+ handled = true;
4089
+ break;
4090
+ case 'ArrowLeft':
4091
+ newDate.setDate(date.getDate() - 1);
4092
+ handled = true;
4093
+ break;
4094
+ case 'ArrowDown':
4095
+ newDate.setDate(date.getDate() + 7);
4096
+ handled = true;
4097
+ break;
4098
+ case 'ArrowUp':
4099
+ newDate.setDate(date.getDate() - 7);
4100
+ handled = true;
4101
+ break;
4102
+ case 'PageDown':
4103
+ newDate.setMonth(date.getMonth() + 1);
4104
+ handled = true;
4105
+ break;
4106
+ case 'PageUp':
4107
+ newDate.setMonth(date.getMonth() - 1);
4108
+ handled = true;
4109
+ break;
4110
+ // Space and Enter are natively handled by the button's click event
4111
+ }
4112
+ if (handled) {
4113
+ event.preventDefault();
4114
+ this.ensureDateVisible(newDate);
4115
+ this.focusedDate.set(newDate);
4116
+ setTimeout(() => {
4117
+ const buttons = this.#selfRef.nativeElement.querySelectorAll('button');
4118
+ if (buttons) {
4119
+ const targetAria = this.getAriaLabel(newDate);
4120
+ for (let i = 0; i < buttons.length; i++) {
4121
+ if (buttons[i].getAttribute('aria-label') === targetAria) {
4122
+ buttons[i].focus();
4123
+ break;
4124
+ }
4125
+ }
4126
+ }
4127
+ });
4128
+ }
4129
+ }
4130
+ ensureDateVisible(date) {
4131
+ const start = this.currentDate();
4132
+ const end = this.getLastVisibleMonth();
4133
+ if (date < new Date(start.getFullYear(), start.getMonth(), 1)) {
4134
+ this.currentDate.set(new Date(date.getFullYear(), date.getMonth(), 1));
4135
+ this.#findSelectedAndCalc();
4136
+ }
4137
+ else if (date > new Date(end.getFullYear(), end.getMonth() + 1, 0)) {
4138
+ const newStart = new Date(date);
4139
+ newStart.setMonth(newStart.getMonth() - this.monthsToShow() + 1);
4140
+ newStart.setDate(1);
4141
+ this.currentDate.set(newStart);
4142
+ this.#findSelectedAndCalc();
4143
+ }
4144
+ }
4145
+ focusActiveDate() {
4146
+ setTimeout(() => {
4147
+ const activeBtn = this.#selfRef.nativeElement.querySelector('button[tabindex="0"]');
4148
+ if (activeBtn)
4149
+ activeBtn.focus();
4150
+ }, 50);
4151
+ }
4152
+ onFocusOut(event) {
4153
+ setTimeout(() => {
4154
+ const activeElement = document.activeElement;
4155
+ if (activeElement &&
4156
+ activeElement !== document.body &&
4157
+ !this.#selfRef.nativeElement.contains(activeElement)) {
4158
+ this.tabbedOut.emit();
4159
+ }
4160
+ });
4161
+ }
3954
4162
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipDatepicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3955
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipDatepicker, isStandalone: true, selector: "sh-datepicker", inputs: { date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, endDate: { classPropertyName: "endDate", publicName: "endDate", isSignal: true, isRequired: false, transformFunction: null }, asRange: { classPropertyName: "asRange", publicName: "asRange", isSignal: true, isRequired: false, transformFunction: null }, monthsToShow: { classPropertyName: "monthsToShow", publicName: "monthsToShow", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, startOfWeek: { classPropertyName: "startOfWeek", publicName: "startOfWeek", isSignal: true, isRequired: false, transformFunction: null }, weekdayLabels: { classPropertyName: "weekdayLabels", publicName: "weekdayLabels", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { date: "dateChange", endDate: "endDateChange" }, host: { properties: { "class.as-range": "asRange()", "class": "\"columns-\" + monthsToShow()", "class.disabled": "disabled()" } }, viewQueries: [{ propertyName: "daysRef", first: true, predicate: ["daysRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
4163
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipDatepicker, isStandalone: true, selector: "sh-datepicker", inputs: { date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, endDate: { classPropertyName: "endDate", publicName: "endDate", isSignal: true, isRequired: false, transformFunction: null }, asRange: { classPropertyName: "asRange", publicName: "asRange", isSignal: true, isRequired: false, transformFunction: null }, activeRangeSelection: { classPropertyName: "activeRangeSelection", publicName: "activeRangeSelection", isSignal: true, isRequired: false, transformFunction: null }, monthsToShow: { classPropertyName: "monthsToShow", publicName: "monthsToShow", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, startOfWeek: { classPropertyName: "startOfWeek", publicName: "startOfWeek", isSignal: true, isRequired: false, transformFunction: null }, weekdayLabels: { classPropertyName: "weekdayLabels", publicName: "weekdayLabels", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { date: "dateChange", endDate: "endDateChange", tabbedOut: "tabbedOut" }, host: { listeners: { "focusout": "onFocusOut($event)" }, properties: { "class.as-range": "asRange()", "class": "\"columns-\" + monthsToShow()", "class.disabled": "disabled()" } }, viewQueries: [{ propertyName: "daysRef", first: true, predicate: ["daysRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
3956
4164
  <header>
3957
- <button (click)="previousMonth()"><sh-icon>caret-left</sh-icon></button>
4165
+ <button tabindex="-1" (click)="previousMonth()"><sh-icon>caret-left</sh-icon></button>
3958
4166
  <div class="title">
3959
4167
  {{ getMonthName(currentDate()!) }}
3960
4168
  @if (monthsToShow() > 1) {
@@ -3962,7 +4170,7 @@ class ShipDatepicker {
3962
4170
  }
3963
4171
  {{ getFullYear(currentDate()!) }}
3964
4172
  </div>
3965
- <button (click)="nextMonth()"><sh-icon>caret-right</sh-icon></button>
4173
+ <button tabindex="-1" (click)="nextMonth()"><sh-icon>caret-right</sh-icon></button>
3966
4174
  </header>
3967
4175
 
3968
4176
  <section class="months-container">
@@ -3976,13 +4184,18 @@ class ShipDatepicker {
3976
4184
 
3977
4185
  <div class="days" #daysRef>
3978
4186
  @for (calDate of getMonthDates(monthOffset); track $index) {
3979
- <div
4187
+ <button
4188
+ type="button"
3980
4189
  #elementRef
3981
4190
  [class.out-of-scope]="!isCurrentMonth(calDate, monthOffset)"
3982
4191
  [class]="isDateSelected(calDate)"
4192
+ [attr.aria-label]="getAriaLabel(calDate)"
4193
+ [attr.tabindex]="getTabIndex(calDate)"
4194
+ [attr.aria-selected]="isDateSelectedBool(calDate)"
4195
+ (keydown)="onKeydown($event, calDate)"
3983
4196
  (click)="setDate(calDate, elementRef)">
3984
4197
  {{ calDate.getDate() }}
3985
- </div>
4198
+ </button>
3986
4199
  }
3987
4200
 
3988
4201
  @if (!asRange()) {
@@ -4003,7 +4216,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4003
4216
  imports: [ShipIcon],
4004
4217
  template: `
4005
4218
  <header>
4006
- <button (click)="previousMonth()"><sh-icon>caret-left</sh-icon></button>
4219
+ <button tabindex="-1" (click)="previousMonth()"><sh-icon>caret-left</sh-icon></button>
4007
4220
  <div class="title">
4008
4221
  {{ getMonthName(currentDate()!) }}
4009
4222
  @if (monthsToShow() > 1) {
@@ -4011,7 +4224,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4011
4224
  }
4012
4225
  {{ getFullYear(currentDate()!) }}
4013
4226
  </div>
4014
- <button (click)="nextMonth()"><sh-icon>caret-right</sh-icon></button>
4227
+ <button tabindex="-1" (click)="nextMonth()"><sh-icon>caret-right</sh-icon></button>
4015
4228
  </header>
4016
4229
 
4017
4230
  <section class="months-container">
@@ -4025,13 +4238,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4025
4238
 
4026
4239
  <div class="days" #daysRef>
4027
4240
  @for (calDate of getMonthDates(monthOffset); track $index) {
4028
- <div
4241
+ <button
4242
+ type="button"
4029
4243
  #elementRef
4030
4244
  [class.out-of-scope]="!isCurrentMonth(calDate, monthOffset)"
4031
4245
  [class]="isDateSelected(calDate)"
4246
+ [attr.aria-label]="getAriaLabel(calDate)"
4247
+ [attr.tabindex]="getTabIndex(calDate)"
4248
+ [attr.aria-selected]="isDateSelectedBool(calDate)"
4249
+ (keydown)="onKeydown($event, calDate)"
4032
4250
  (click)="setDate(calDate, elementRef)">
4033
4251
  {{ calDate.getDate() }}
4034
- </div>
4252
+ </button>
4035
4253
  }
4036
4254
 
4037
4255
  @if (!asRange()) {
@@ -4051,12 +4269,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4051
4269
  '[class.disabled]': 'disabled()',
4052
4270
  },
4053
4271
  }]
4054
- }], propDecorators: { date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }, { type: i0.Output, args: ["dateChange"] }], endDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "endDate", required: false }] }, { type: i0.Output, args: ["endDateChange"] }], asRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "asRange", required: false }] }], monthsToShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthsToShow", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], startOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "startOfWeek", required: false }] }], weekdayLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekdayLabels", required: false }] }], daysRef: [{ type: i0.ViewChild, args: ['daysRef', { isSignal: true }] }] } });
4272
+ }], propDecorators: { date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }, { type: i0.Output, args: ["dateChange"] }], endDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "endDate", required: false }] }, { type: i0.Output, args: ["endDateChange"] }], asRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "asRange", required: false }] }], activeRangeSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeRangeSelection", required: false }] }], monthsToShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthsToShow", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], tabbedOut: [{ type: i0.Output, args: ["tabbedOut"] }], startOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "startOfWeek", required: false }] }], weekdayLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekdayLabels", required: false }] }], daysRef: [{ type: i0.ViewChild, args: ['daysRef', { isSignal: true }] }], onFocusOut: [{
4273
+ type: HostListener,
4274
+ args: ['focusout', ['$event']]
4275
+ }] } });
4055
4276
 
4056
4277
  class ShipDatepickerInput {
4057
4278
  constructor() {
4058
4279
  // #INIT_DATE = this.#getUTCDate(new Date());
4059
- this.ngModels = contentChild(NgModel, ...(ngDevMode ? [{ debugName: "ngModels" }] : /* istanbul ignore next */ []));
4280
+ this.#selfRef = inject(ElementRef);
4281
+ this.ngControl = contentChild(NgControl, ...(ngDevMode ? [{ debugName: "ngControl" }] : /* istanbul ignore next */ []));
4060
4282
  this.#datePipe = inject(DatePipe);
4061
4283
  this.#inputRef = signal(null, ...(ngDevMode ? [{ debugName: "#inputRef" }] : /* istanbul ignore next */ []));
4062
4284
  this.masking = input('mediumDate', ...(ngDevMode ? [{ debugName: "masking" }] : /* istanbul ignore next */ []));
@@ -4074,6 +4296,14 @@ class ShipDatepickerInput {
4074
4296
  this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
4075
4297
  this.currentClass = classMutationSignal();
4076
4298
  this.#inputObserver = contentProjectionSignal('#input-wrap input');
4299
+ this.datepicker = viewChild(ShipDatepicker, ...(ngDevMode ? [{ debugName: "datepicker" }] : /* istanbul ignore next */ []));
4300
+ this.#isOpenEffect = effect(() => {
4301
+ if (this.isOpen()) {
4302
+ setTimeout(() => {
4303
+ this.datepicker()?.focusActiveDate();
4304
+ }, 50);
4305
+ }
4306
+ }, ...(ngDevMode ? [{ debugName: "#isOpenEffect" }] : /* istanbul ignore next */ []));
4077
4307
  this.#inputRefEffect = effect(() => {
4078
4308
  const inputs = this.#inputObserver();
4079
4309
  if (!inputs.length)
@@ -4083,11 +4313,30 @@ class ShipDatepickerInput {
4083
4313
  return;
4084
4314
  this.#createCustomInputEventListener(input);
4085
4315
  input.addEventListener('inputValueChanged', (event) => {
4086
- this.internalDate.set(event.detail.value ? new Date(event.detail.value) : null);
4316
+ const val = event.detail.value;
4317
+ if (!val) {
4318
+ this.internalDate.set(null);
4319
+ return;
4320
+ }
4321
+ let newD = new Date(val);
4322
+ if (isNaN(newD.getTime())) {
4323
+ // If it's a time-only string like "14:30" or "14:30:00"
4324
+ if (typeof val === 'string' && /^(\d{2}):(\d{2})/.test(val)) {
4325
+ const match = val.match(/^(\d{2}):(\d{2})(?::(\d{2}))?/);
4326
+ if (match) {
4327
+ const current = this.internalDate() || new Date();
4328
+ newD = new Date(current);
4329
+ newD.setHours(parseInt(match[1], 10), parseInt(match[2], 10), match[3] ? parseInt(match[3], 10) : 0, 0);
4330
+ }
4331
+ }
4332
+ }
4333
+ if (!isNaN(newD.getTime())) {
4334
+ this.internalDate.set(newD);
4335
+ }
4087
4336
  });
4088
4337
  input.addEventListener('focus', () => {
4089
4338
  this.isOpen.set(true);
4090
- input.blur();
4339
+ // Removed input.blur() so users can actually type or use Shift+Tab to navigate backward
4091
4340
  });
4092
4341
  this.#inputRef.set(input);
4093
4342
  input.autocomplete = 'off';
@@ -4096,15 +4345,34 @@ class ShipDatepickerInput {
4096
4345
  }
4097
4346
  }, ...(ngDevMode ? [{ debugName: "#inputRefEffect" }] : /* istanbul ignore next */ []));
4098
4347
  }
4348
+ // #INIT_DATE = this.#getUTCDate(new Date());
4349
+ #selfRef;
4099
4350
  #datePipe;
4100
4351
  #inputRef;
4101
4352
  #inputObserver;
4353
+ #isOpenEffect;
4354
+ onFocusOut(event) {
4355
+ setTimeout(() => {
4356
+ const activeElement = document.activeElement;
4357
+ if (activeElement &&
4358
+ activeElement !== document.body &&
4359
+ !this.#selfRef.nativeElement.contains(activeElement)) {
4360
+ this.isOpen.set(false);
4361
+ }
4362
+ });
4363
+ }
4102
4364
  onDateChange(date) {
4103
4365
  this.internalDate.set(date);
4104
- const input = this.#inputRef();
4105
- if (input) {
4106
- input.value = date ? date.toString() : '';
4107
- input.dispatchEvent(new Event('input'));
4366
+ const control = this.ngControl()?.control;
4367
+ if (control) {
4368
+ control.setValue(date);
4369
+ }
4370
+ else {
4371
+ const input = this.#inputRef();
4372
+ if (input) {
4373
+ input.value = date ? date.toString() : '';
4374
+ input.dispatchEvent(new Event('input'));
4375
+ }
4108
4376
  }
4109
4377
  }
4110
4378
  close() {
@@ -4135,7 +4403,7 @@ class ShipDatepickerInput {
4135
4403
  return input;
4136
4404
  }
4137
4405
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipDatepickerInput, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4138
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipDatepickerInput, isStandalone: true, selector: "sh-datepicker-input", inputs: { masking: { classPropertyName: "masking", publicName: "masking", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", isOpen: "isOpenChange" }, providers: [DatePipe], queries: [{ propertyName: "ngModels", first: true, predicate: NgModel, descendants: true, isSignal: true }], ngImport: i0, template: `
4406
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipDatepickerInput, isStandalone: true, selector: "sh-datepicker-input", inputs: { masking: { classPropertyName: "masking", publicName: "masking", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", isOpen: "isOpenChange" }, host: { listeners: { "focusout": "onFocusOut($event)" } }, providers: [DatePipe], queries: [{ propertyName: "ngControl", first: true, predicate: NgControl, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "datepicker", first: true, predicate: ShipDatepicker, descendants: true, isSignal: true }], ngImport: i0, template: `
4139
4407
  <sh-form-field-popover (closed)="close()" [(isOpen)]="isOpen">
4140
4408
  <ng-content select="label" ngProjectAs="label" />
4141
4409
 
@@ -4157,13 +4425,13 @@ class ShipDatepickerInput {
4157
4425
 
4158
4426
  <div popoverContent>
4159
4427
  @if (this.isOpen()) {
4160
- <sh-datepicker [date]="internalDate()" (dateChange)="onDateChange($event)" [class]="currentClass()" />
4428
+ <sh-datepicker [date]="internalDate()" (dateChange)="onDateChange($event)" (tabbedOut)="isOpen.set(false)" [class]="currentClass()" />
4161
4429
  }
4162
4430
  </div>
4163
4431
  </sh-form-field-popover>
4164
4432
 
4165
4433
  <ng-template #defaultIndicator></ng-template>
4166
- `, isInline: true, dependencies: [{ kind: "component", type: ShipDatepicker, selector: "sh-datepicker", inputs: ["date", "endDate", "asRange", "monthsToShow", "disabled", "startOfWeek", "weekdayLabels"], outputs: ["dateChange", "endDateChange"] }, { kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen", "color", "variant", "size", "readonly"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4434
+ `, isInline: true, dependencies: [{ kind: "component", type: ShipDatepicker, selector: "sh-datepicker", inputs: ["date", "endDate", "asRange", "activeRangeSelection", "monthsToShow", "disabled", "startOfWeek", "weekdayLabels"], outputs: ["dateChange", "endDateChange", "tabbedOut"] }, { kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen", "color", "variant", "size", "readonly"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4167
4435
  }
4168
4436
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipDatepickerInput, decorators: [{
4169
4437
  type: Component,
@@ -4193,7 +4461,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4193
4461
 
4194
4462
  <div popoverContent>
4195
4463
  @if (this.isOpen()) {
4196
- <sh-datepicker [date]="internalDate()" (dateChange)="onDateChange($event)" [class]="currentClass()" />
4464
+ <sh-datepicker [date]="internalDate()" (dateChange)="onDateChange($event)" (tabbedOut)="isOpen.set(false)" [class]="currentClass()" />
4197
4465
  }
4198
4466
  </div>
4199
4467
  </sh-form-field-popover>
@@ -4202,25 +4470,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4202
4470
  `,
4203
4471
  changeDetection: ChangeDetectionStrategy.OnPush,
4204
4472
  }]
4205
- }], propDecorators: { ngModels: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NgModel), { isSignal: true }] }], masking: [{ type: i0.Input, args: [{ isSignal: true, alias: "masking", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }] } });
4473
+ }], propDecorators: { ngControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NgControl), { isSignal: true }] }], masking: [{ type: i0.Input, args: [{ isSignal: true, alias: "masking", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], datepicker: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ShipDatepicker), { isSignal: true }] }], onFocusOut: [{
4474
+ type: HostListener,
4475
+ args: ['focusout', ['$event']]
4476
+ }] } });
4206
4477
 
4207
4478
  class ShipDaterangeInput {
4208
4479
  #selfRef;
4480
+ #inputObserver;
4209
4481
  #datePipe;
4482
+ #isOpenEffect;
4210
4483
  get classes() {
4211
4484
  return `${this.#selfRef.nativeElement.classList.value}`;
4212
4485
  }
4213
4486
  constructor() {
4214
4487
  this.#selfRef = inject(ElementRef);
4215
- this.startDateInputs = contentChildren('startDate', ...(ngDevMode ? [{ debugName: "startDateInputs" }] : /* istanbul ignore next */ []));
4216
- this.endDateInputs = contentChildren('endDate', ...(ngDevMode ? [{ debugName: "endDateInputs" }] : /* istanbul ignore next */ []));
4488
+ this.#inputObserver = contentProjectionSignal('input', {
4489
+ childList: true,
4490
+ subtree: true,
4491
+ });
4217
4492
  this.#datePipe = inject(DatePipe);
4218
4493
  this.monthsToShow = input(1, ...(ngDevMode ? [{ debugName: "monthsToShow" }] : /* istanbul ignore next */ []));
4219
4494
  this.masking = input('mediumDate', ...(ngDevMode ? [{ debugName: "masking" }] : /* istanbul ignore next */ []));
4220
4495
  this.closed = output();
4221
4496
  this.startDate = signal(null, ...(ngDevMode ? [{ debugName: "startDate" }] : /* istanbul ignore next */ []));
4222
4497
  this.endDate = signal(null, ...(ngDevMode ? [{ debugName: "endDate" }] : /* istanbul ignore next */ []));
4498
+ this.activeInput = signal('start', ...(ngDevMode ? [{ debugName: "activeInput" }] : /* istanbul ignore next */ []));
4223
4499
  this.isOpen = model(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
4500
+ this.datepicker = viewChild(ShipDatepicker, ...(ngDevMode ? [{ debugName: "datepicker" }] : /* istanbul ignore next */ []));
4501
+ this.#isOpenEffect = effect(() => {
4502
+ if (this.isOpen()) {
4503
+ setTimeout(() => {
4504
+ this.datepicker()?.focusActiveDate();
4505
+ }, 50);
4506
+ }
4507
+ }, ...(ngDevMode ? [{ debugName: "#isOpenEffect" }] : /* istanbul ignore next */ []));
4224
4508
  this._maskedStartDate = computed(() => {
4225
4509
  const date = this.startDate();
4226
4510
  const mask = this.masking();
@@ -4236,22 +4520,32 @@ class ShipDaterangeInput {
4236
4520
  return this.#datePipe.transform(date, mask);
4237
4521
  }, ...(ngDevMode ? [{ debugName: "_maskedEndDate" }] : /* istanbul ignore next */ []));
4238
4522
  effect(() => {
4239
- // Setup start date inputs
4240
- this.startDateInputs().forEach((input) => {
4241
- this.setupInput(input, true);
4242
- });
4243
- // Setup end date inputs
4244
- this.endDateInputs().forEach((input) => {
4245
- this.setupInput(input, false);
4246
- });
4523
+ const inputs = this.#inputObserver();
4524
+ if (inputs.length === 0)
4525
+ return;
4526
+ if (inputs[0])
4527
+ this.setupInput(inputs[0], true);
4528
+ if (inputs[1])
4529
+ this.setupInput(inputs[1], false);
4247
4530
  });
4248
4531
  }
4249
- setupInput(input, isStart) {
4250
- const element = input.nativeElement;
4532
+ setupInput(element, isStart) {
4533
+ if (element._hasCustomFocusEvent)
4534
+ return;
4535
+ element._hasCustomFocusEvent = true;
4251
4536
  element.autocomplete = 'off';
4537
+ // Set tabindex -1 on the second input to prevent users from having to Shift+Tab
4538
+ // multiple times to exit the component when masking is enabled.
4539
+ if (!isStart) {
4540
+ element.tabIndex = -1;
4541
+ }
4252
4542
  element.addEventListener('focus', () => {
4543
+ this.activeInput.set(isStart ? 'start' : 'end');
4544
+ if (element._ignoreNextFocus) {
4545
+ element._ignoreNextFocus = false;
4546
+ return;
4547
+ }
4253
4548
  this.isOpen.set(true);
4254
- element.blur();
4255
4549
  });
4256
4550
  // Handle initial value
4257
4551
  if (element.value) {
@@ -4271,26 +4565,47 @@ class ShipDaterangeInput {
4271
4565
  }
4272
4566
  }
4273
4567
  }
4568
+ onFocusOut(event) {
4569
+ setTimeout(() => {
4570
+ const activeElement = document.activeElement;
4571
+ if (activeElement &&
4572
+ activeElement !== document.body &&
4573
+ !this.#selfRef.nativeElement.contains(activeElement)) {
4574
+ this.isOpen.set(false);
4575
+ }
4576
+ });
4577
+ }
4274
4578
  onStartDateChange(date) {
4275
4579
  this.startDate.set(date);
4276
- this.updateInputValue(this.startDateInputs(), date);
4580
+ const inputs = this.#inputObserver();
4581
+ if (inputs[0])
4582
+ this.updateInputValue([inputs[0]], date);
4583
+ // Automatically switch to end date selection
4584
+ this.activeInput.set('end');
4277
4585
  }
4278
4586
  onEndDateChange(date) {
4279
4587
  this.endDate.set(date);
4280
- this.updateInputValue(this.endDateInputs(), date);
4588
+ const inputs = this.#inputObserver();
4589
+ if (inputs[1])
4590
+ this.updateInputValue([inputs[1]], date);
4281
4591
  if (this.startDate() && date) {
4282
4592
  this.isOpen.set(false);
4593
+ const inputs = this.#inputObserver();
4594
+ if (inputs[0] && document.activeElement !== inputs[0]) {
4595
+ inputs[0]._ignoreNextFocus = true;
4596
+ inputs[0].focus();
4597
+ }
4283
4598
  }
4284
4599
  }
4285
4600
  updateInputValue(inputs, date) {
4286
4601
  inputs.forEach((input) => {
4287
4602
  if (this.masking()) {
4288
- input.nativeElement.value = this.#datePipe.transform(date, this.masking()) ?? '';
4603
+ input.value = this.#datePipe.transform(date, this.masking()) ?? '';
4289
4604
  }
4290
4605
  else {
4291
- input.nativeElement.value = date ? date.toUTCString() : '';
4606
+ input.value = date ? date.toUTCString() : '';
4292
4607
  }
4293
- this.dispatchInputEvent(input.nativeElement);
4608
+ this.dispatchInputEvent(input);
4294
4609
  });
4295
4610
  }
4296
4611
  dispatchInputEvent(input) {
@@ -4304,16 +4619,20 @@ class ShipDaterangeInput {
4304
4619
  });
4305
4620
  }
4306
4621
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipDaterangeInput, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4307
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipDaterangeInput, isStandalone: true, selector: "sh-daterange-input", inputs: { monthsToShow: { classPropertyName: "monthsToShow", publicName: "monthsToShow", isSignal: true, isRequired: false, transformFunction: null }, masking: { classPropertyName: "masking", publicName: "masking", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", isOpen: "isOpenChange" }, providers: [DatePipe], queries: [{ propertyName: "startDateInputs", predicate: ["startDate"], isSignal: true }, { propertyName: "endDateInputs", predicate: ["endDate"], isSignal: true }], ngImport: i0, template: `
4622
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipDaterangeInput, isStandalone: true, selector: "sh-daterange-input", inputs: { monthsToShow: { classPropertyName: "monthsToShow", publicName: "monthsToShow", isSignal: true, isRequired: false, transformFunction: null }, masking: { classPropertyName: "masking", publicName: "masking", isSignal: true, isRequired: false, transformFunction: null }, isOpen: { classPropertyName: "isOpen", publicName: "isOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", isOpen: "isOpenChange" }, host: { listeners: { "focusout": "onFocusOut($event)" } }, providers: [DatePipe], viewQueries: [{ propertyName: "datepicker", first: true, predicate: ShipDatepicker, descendants: true, isSignal: true }], ngImport: i0, template: `
4308
4623
  <sh-form-field-popover [class]="'columns-' + monthsToShow()" (closed)="close()" [(isOpen)]="isOpen">
4309
4624
  <ng-content select="label" ngProjectAs="label" />
4310
4625
 
4311
4626
  <ng-content select="[prefix]" ngProjectAs="[prefix]" />
4312
4627
  <ng-content select="[textPrefix]" ngProjectAs="[textPrefix]" />
4313
4628
 
4314
- <div class="input" ngProjectAs="input" #inputWrap>
4629
+ <div class="input" ngProjectAs="input" #inputWrap [class.active-start]="isOpen() && activeInput() === 'start'" [class.active-end]="isOpen() && activeInput() === 'end'">
4315
4630
  @if (this.masking()) {
4316
- <div class="masked-value">{{ _maskedStartDate() ?? 'N/A' }} - {{ _maskedEndDate() ?? 'N/A' }}</div>
4631
+ <div class="masked-value" [class.active-start]="isOpen() && activeInput() === 'start'" [class.active-end]="isOpen() && activeInput() === 'end'">
4632
+ <span class="start-val">{{ _maskedStartDate() ?? 'N/A' }}</span>
4633
+ <span class="separator">-</span>
4634
+ <span class="end-val">{{ _maskedEndDate() ?? 'N/A' }}</span>
4635
+ </div>
4317
4636
  }
4318
4637
  <ng-content select="input" />
4319
4638
  </div>
@@ -4327,15 +4646,17 @@ class ShipDaterangeInput {
4327
4646
  <sh-datepicker
4328
4647
  [date]="startDate()"
4329
4648
  [endDate]="endDate()"
4649
+ [activeRangeSelection]="activeInput()"
4330
4650
  [class]="classes"
4331
4651
  (dateChange)="onStartDateChange($event)"
4332
4652
  (endDateChange)="onEndDateChange($event)"
4653
+ (tabbedOut)="isOpen.set(false)"
4333
4654
  [monthsToShow]="monthsToShow()"
4334
4655
  [asRange]="true" />
4335
4656
  }
4336
4657
  </div>
4337
4658
  </sh-form-field-popover>
4338
- `, isInline: true, dependencies: [{ kind: "component", type: ShipDatepicker, selector: "sh-datepicker", inputs: ["date", "endDate", "asRange", "monthsToShow", "disabled", "startOfWeek", "weekdayLabels"], outputs: ["dateChange", "endDateChange"] }, { kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen", "color", "variant", "size", "readonly"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4659
+ `, isInline: true, dependencies: [{ kind: "component", type: ShipDatepicker, selector: "sh-datepicker", inputs: ["date", "endDate", "asRange", "activeRangeSelection", "monthsToShow", "disabled", "startOfWeek", "weekdayLabels"], outputs: ["dateChange", "endDateChange", "tabbedOut"] }, { kind: "component", type: ShipFormFieldPopover, selector: "sh-form-field-popover", inputs: ["isOpen", "color", "variant", "size", "readonly"], outputs: ["isOpenChange", "closed"] }, { kind: "component", type: ShipIcon, selector: "sh-icon", inputs: ["color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4339
4660
  }
4340
4661
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipDaterangeInput, decorators: [{
4341
4662
  type: Component,
@@ -4350,9 +4671,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4350
4671
  <ng-content select="[prefix]" ngProjectAs="[prefix]" />
4351
4672
  <ng-content select="[textPrefix]" ngProjectAs="[textPrefix]" />
4352
4673
 
4353
- <div class="input" ngProjectAs="input" #inputWrap>
4674
+ <div class="input" ngProjectAs="input" #inputWrap [class.active-start]="isOpen() && activeInput() === 'start'" [class.active-end]="isOpen() && activeInput() === 'end'">
4354
4675
  @if (this.masking()) {
4355
- <div class="masked-value">{{ _maskedStartDate() ?? 'N/A' }} - {{ _maskedEndDate() ?? 'N/A' }}</div>
4676
+ <div class="masked-value" [class.active-start]="isOpen() && activeInput() === 'start'" [class.active-end]="isOpen() && activeInput() === 'end'">
4677
+ <span class="start-val">{{ _maskedStartDate() ?? 'N/A' }}</span>
4678
+ <span class="separator">-</span>
4679
+ <span class="end-val">{{ _maskedEndDate() ?? 'N/A' }}</span>
4680
+ </div>
4356
4681
  }
4357
4682
  <ng-content select="input" />
4358
4683
  </div>
@@ -4366,9 +4691,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4366
4691
  <sh-datepicker
4367
4692
  [date]="startDate()"
4368
4693
  [endDate]="endDate()"
4694
+ [activeRangeSelection]="activeInput()"
4369
4695
  [class]="classes"
4370
4696
  (dateChange)="onStartDateChange($event)"
4371
4697
  (endDateChange)="onEndDateChange($event)"
4698
+ (tabbedOut)="isOpen.set(false)"
4372
4699
  [monthsToShow]="monthsToShow()"
4373
4700
  [asRange]="true" />
4374
4701
  }
@@ -4377,7 +4704,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
4377
4704
  `,
4378
4705
  changeDetection: ChangeDetectionStrategy.OnPush,
4379
4706
  }]
4380
- }], ctorParameters: () => [], propDecorators: { startDateInputs: [{ type: i0.ContentChildren, args: ['startDate', { isSignal: true }] }], endDateInputs: [{ type: i0.ContentChildren, args: ['endDate', { isSignal: true }] }], monthsToShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthsToShow", required: false }] }], masking: [{ type: i0.Input, args: [{ isSignal: true, alias: "masking", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }] } });
4707
+ }], ctorParameters: () => [], propDecorators: { monthsToShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthsToShow", required: false }] }], masking: [{ type: i0.Input, args: [{ isSignal: true, alias: "masking", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }, { type: i0.Output, args: ["isOpenChange"] }], datepicker: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ShipDatepicker), { isSignal: true }] }], onFocusOut: [{
4708
+ type: HostListener,
4709
+ args: ['focusout', ['$event']]
4710
+ }] } });
4381
4711
 
4382
4712
  class ShipDivider {
4383
4713
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipDivider, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
@@ -4464,6 +4794,33 @@ class ShipFormField {
4464
4794
  readonly: this.readonly,
4465
4795
  });
4466
4796
  afterNextRender(() => {
4797
+ const el = this.#selfRef.nativeElement;
4798
+ const inputEl = el.querySelector('input') || el.querySelector('textarea');
4799
+ const labelEl = el.querySelector('label');
4800
+ const errorEl = el.querySelector('[error]');
4801
+ const hintEl = el.querySelector('[hint]');
4802
+ if (inputEl) {
4803
+ if (!inputEl.id) {
4804
+ inputEl.id = `sh-input-${Math.random().toString(36).substring(2, 9)}`;
4805
+ }
4806
+ if (labelEl && !labelEl.getAttribute('for')) {
4807
+ labelEl.setAttribute('for', inputEl.id);
4808
+ }
4809
+ const describedBy = [];
4810
+ if (errorEl) {
4811
+ if (!errorEl.id)
4812
+ errorEl.id = `sh-error-${Math.random().toString(36).substring(2, 9)}`;
4813
+ describedBy.push(errorEl.id);
4814
+ }
4815
+ if (hintEl) {
4816
+ if (!hintEl.id)
4817
+ hintEl.id = `sh-hint-${Math.random().toString(36).substring(2, 9)}`;
4818
+ describedBy.push(hintEl.id);
4819
+ }
4820
+ if (describedBy.length > 0 && !inputEl.hasAttribute('aria-describedby')) {
4821
+ inputEl.setAttribute('aria-describedby', describedBy.join(' '));
4822
+ }
4823
+ }
4467
4824
  const supportFieldSizing = typeof CSS !== 'undefined' && CSS.supports('field-sizing', 'content');
4468
4825
  const text = this.#selfRef.nativeElement.querySelector('textarea');
4469
4826
  if (!supportFieldSizing && text !== null) {
@@ -5374,7 +5731,7 @@ class ShipRadio {
5374
5731
  event.preventDefault();
5375
5732
  }
5376
5733
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipRadio, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5377
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipRadio, isStandalone: true, selector: "sh-radio", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, noInternalInput: { classPropertyName: "noInternalInput", publicName: "noInternalInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, host: { listeners: { "keydown.enter": "onEnter($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() ? \"\" : null" } }, viewQueries: [{ propertyName: "internalInput", first: true, predicate: ["internalInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
5734
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipRadio, isStandalone: true, selector: "sh-radio", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, noInternalInput: { classPropertyName: "noInternalInput", publicName: "noInternalInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, host: { listeners: { "keydown.enter": "onEnter($event)", "keydown.space": "onEnter($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() ? \"\" : null", "attr.role": "noInternalInput() ? \"radio\" : null", "attr.aria-checked": "noInternalInput() ? checked() : null", "attr.tabindex": "noInternalInput() ? (disabled() ? \"-1\" : \"0\") : null" } }, viewQueries: [{ propertyName: "internalInput", first: true, predicate: ["internalInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
5378
5735
  <div class="radio sh-sheet" [class]="currentClassList()"></div>
5379
5736
 
5380
5737
  <ng-content />
@@ -5414,11 +5771,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
5414
5771
  host: {
5415
5772
  '[class]': 'hostClasses()',
5416
5773
  '[attr.disabled]': 'disabled() ? "" : null',
5774
+ '[attr.role]': 'noInternalInput() ? "radio" : null',
5775
+ '[attr.aria-checked]': 'noInternalInput() ? checked() : null',
5776
+ '[attr.tabindex]': 'noInternalInput() ? (disabled() ? "-1" : "0") : null',
5417
5777
  },
5418
5778
  }]
5419
5779
  }], propDecorators: { internalInput: [{ type: i0.ViewChild, args: ['internalInput', { isSignal: true }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], noInternalInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "noInternalInput", required: false }] }], onEnter: [{
5420
5780
  type: HostListener,
5421
5781
  args: ['keydown.enter', ['$event']]
5782
+ }, {
5783
+ type: HostListener,
5784
+ args: ['keydown.space', ['$event']]
5422
5785
  }] } });
5423
5786
 
5424
5787
  class ShipRangeSlider {
@@ -5742,6 +6105,11 @@ class ShipSelect {
5742
6105
  this.selectedOptions = model([], ...(ngDevMode ? [{ debugName: "selectedOptions" }] : /* istanbul ignore next */ []));
5743
6106
  this.cleared = output();
5744
6107
  this.onAddNewFreeTextOption = output();
6108
+ this.spacedSelectedOptions = computed(() => {
6109
+ const selectedOptions = this.selectedOptions();
6110
+ const valueKey = this.value();
6111
+ return selectedOptions.map((option) => (valueKey ? this.#getProperty(option, valueKey) : option)).join(', ');
6112
+ }, ...(ngDevMode ? [{ debugName: "spacedSelectedOptions" }] : /* istanbul ignore next */ []));
5745
6113
  this.computedFreeTextOption = computed(() => {
5746
6114
  const inputValue = this.inputValue();
5747
6115
  const valueKey = this.value();
@@ -5820,7 +6188,7 @@ class ShipSelect {
5820
6188
  scoredOptions.sort((a, b) => b.score - a.score);
5821
6189
  return scoredOptions.map((scoredOption) => scoredOption.item);
5822
6190
  }, ...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
5823
- this.#componentId = generateUniqueId();
6191
+ this.componentId = generateUniqueId();
5824
6192
  this.inputRefEl = computed(() => {
5825
6193
  const inputRefInput = this.inputRefInput();
5826
6194
  if (inputRefInput === null)
@@ -5832,9 +6200,10 @@ class ShipSelect {
5832
6200
  }
5833
6201
  input.autocomplete = 'off';
5834
6202
  input.setAttribute('role', 'combobox');
5835
- input.setAttribute('id', `combobox-${this.#componentId}`);
6203
+ input.setAttribute('id', `combobox-${this.componentId}`);
5836
6204
  input.setAttribute('aria-haspopup', 'listbox');
5837
- input.setAttribute('aria-owns', 'optionsWrapId');
6205
+ input.setAttribute('aria-owns', `optionsWrapId-${this.componentId}`);
6206
+ input.setAttribute('aria-controls', `optionsWrapId-${this.componentId}`);
5838
6207
  this.#createCustomInputEventListener(input);
5839
6208
  input.addEventListener('focus', () => {
5840
6209
  if (this.readonly())
@@ -5866,9 +6235,9 @@ class ShipSelect {
5866
6235
  const input = this.inputRefEl();
5867
6236
  if (!input)
5868
6237
  return;
5869
- const focusedId = this.getLabelAsSlug(this.filteredOptions()[this.focusedOptionIndex()]);
5870
- if (focusedId) {
5871
- input.setAttribute('aria-activedescendant', focusedId);
6238
+ const index = this.focusedOptionIndex();
6239
+ if (index >= 0 || (index === -1 && this.asFreeText())) {
6240
+ input.setAttribute('aria-activedescendant', this.getOptionId(index));
5872
6241
  }
5873
6242
  else {
5874
6243
  input.removeAttribute('aria-activedescendant');
@@ -6017,7 +6386,6 @@ class ShipSelect {
6017
6386
  score += matchCount * 20;
6018
6387
  return score;
6019
6388
  }
6020
- #componentId;
6021
6389
  #selectedOptionsEffect;
6022
6390
  ngOnInit() {
6023
6391
  this.setInitInput();
@@ -6089,11 +6457,8 @@ class ShipSelect {
6089
6457
  return option;
6090
6458
  return this.#getProperty(option, label);
6091
6459
  }
6092
- getLabelAsSlug(option) {
6093
- const label = this.getLabel(option);
6094
- if (!label || typeof label !== 'string')
6095
- return '';
6096
- return label.replaceAll(' ', '-');
6460
+ getOptionId(index) {
6461
+ return `opt-${this.componentId}-${index}`;
6097
6462
  }
6098
6463
  toggleOptionByIndex(optionIndex, event, enterKey = false) {
6099
6464
  let option = this.filteredOptions()[optionIndex];
@@ -6201,7 +6566,7 @@ class ShipSelect {
6201
6566
  this.isOpen.set(false);
6202
6567
  const prevInputValue = this.prevInputValue();
6203
6568
  const prevSelectedOptions = this.#previousSelectedOptions();
6204
- if (this.asFreeText()) {
6569
+ if (this.asFreeText() && !this.selectMultiple()) {
6205
6570
  this.updateInputElValue();
6206
6571
  return;
6207
6572
  }
@@ -6292,7 +6657,7 @@ class ShipSelect {
6292
6657
  @let _selOptionTemplate = _selectedOptionTemplate || _optionTemplate || _inlineTemplate;
6293
6658
  @let _listOptionTemplate = _optionTemplate || _inlineTemplate;
6294
6659
  @let _asChips = !asText() && selectMultiple();
6295
- @let _showSearchText = isOpen() && hasSearch() && (_asChips || inputValue().length > -1);
6660
+ @let _showSearchText = isOpen() && hasSearch() && (_asChips || inputValue().length > 0);
6296
6661
 
6297
6662
  <sh-popover
6298
6663
  #formFieldWrapper
@@ -6319,7 +6684,7 @@ class ShipSelect {
6319
6684
  <div class="input" [class.show-search-text]="_showSearchText" ngProjectAs="input">
6320
6685
  <div class="selected-value" [class.is-selected]="_inputState === 'selected'">
6321
6686
  @if (asFreeText() && inputValue().length > 0 && !isOpen()) {
6322
- {{ inputValue() }}
6687
+ {{ spacedSelectedOptions() }}
6323
6688
  } @else if (_selectedOptions.length > 0) {
6324
6689
  @for (selectedOption of _selectedOptions; track $index) {
6325
6690
  @if (selectedOption) {
@@ -6379,7 +6744,7 @@ class ShipSelect {
6379
6744
  }
6380
6745
  </sh-form-field>
6381
6746
 
6382
- <div class="ship-options" #optionsWrap id="optionsWrapId" role="listbox">
6747
+ <div class="ship-options" #optionsWrap [id]="'optionsWrapId-' + componentId" role="listbox">
6383
6748
  @if (asFreeText()) {
6384
6749
  @let freeTextOption = computedFreeTextOption();
6385
6750
  @let freeTextOptionValue = getValue(freeTextOption);
@@ -6392,7 +6757,8 @@ class ShipSelect {
6392
6757
  <li
6393
6758
  (click)="toggleOptionByIndex(-1)"
6394
6759
  class="option"
6395
- [id]="this.getLabelAsSlug(freeTextOption)"
6760
+ role="option"
6761
+ [id]="this.getOptionId(-1)"
6396
6762
  [attr.aria-selected]="isSelected(-1)"
6397
6763
  [class.selected]="isSelected(-1)"
6398
6764
  [class.focused]="-1 === focusedOptionIndex()">
@@ -6419,7 +6785,8 @@ class ShipSelect {
6419
6785
  <li
6420
6786
  (click)="toggleOptionByIndex($index)"
6421
6787
  class="option"
6422
- [id]="this.getLabelAsSlug(option)"
6788
+ role="option"
6789
+ [id]="this.getOptionId($index)"
6423
6790
  [attr.aria-selected]="isSelected($index)"
6424
6791
  [class.selected]="isSelected($index)"
6425
6792
  [class.focused]="$index === focusedOptionIndex()">
@@ -6455,7 +6822,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
6455
6822
  @let _selOptionTemplate = _selectedOptionTemplate || _optionTemplate || _inlineTemplate;
6456
6823
  @let _listOptionTemplate = _optionTemplate || _inlineTemplate;
6457
6824
  @let _asChips = !asText() && selectMultiple();
6458
- @let _showSearchText = isOpen() && hasSearch() && (_asChips || inputValue().length > -1);
6825
+ @let _showSearchText = isOpen() && hasSearch() && (_asChips || inputValue().length > 0);
6459
6826
 
6460
6827
  <sh-popover
6461
6828
  #formFieldWrapper
@@ -6482,7 +6849,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
6482
6849
  <div class="input" [class.show-search-text]="_showSearchText" ngProjectAs="input">
6483
6850
  <div class="selected-value" [class.is-selected]="_inputState === 'selected'">
6484
6851
  @if (asFreeText() && inputValue().length > 0 && !isOpen()) {
6485
- {{ inputValue() }}
6852
+ {{ spacedSelectedOptions() }}
6486
6853
  } @else if (_selectedOptions.length > 0) {
6487
6854
  @for (selectedOption of _selectedOptions; track $index) {
6488
6855
  @if (selectedOption) {
@@ -6542,7 +6909,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
6542
6909
  }
6543
6910
  </sh-form-field>
6544
6911
 
6545
- <div class="ship-options" #optionsWrap id="optionsWrapId" role="listbox">
6912
+ <div class="ship-options" #optionsWrap [id]="'optionsWrapId-' + componentId" role="listbox">
6546
6913
  @if (asFreeText()) {
6547
6914
  @let freeTextOption = computedFreeTextOption();
6548
6915
  @let freeTextOptionValue = getValue(freeTextOption);
@@ -6555,7 +6922,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
6555
6922
  <li
6556
6923
  (click)="toggleOptionByIndex(-1)"
6557
6924
  class="option"
6558
- [id]="this.getLabelAsSlug(freeTextOption)"
6925
+ role="option"
6926
+ [id]="this.getOptionId(-1)"
6559
6927
  [attr.aria-selected]="isSelected(-1)"
6560
6928
  [class.selected]="isSelected(-1)"
6561
6929
  [class.focused]="-1 === focusedOptionIndex()">
@@ -6582,7 +6950,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
6582
6950
  <li
6583
6951
  (click)="toggleOptionByIndex($index)"
6584
6952
  class="option"
6585
- [id]="this.getLabelAsSlug(option)"
6953
+ role="option"
6954
+ [id]="this.getOptionId($index)"
6586
6955
  [attr.aria-selected]="isSelected($index)"
6587
6956
  [class.selected]="isSelected($index)"
6588
6957
  [class.focused]="$index === focusedOptionIndex()">
@@ -7310,7 +7679,7 @@ function transferArrayItem(currentArray, targetArray, currentIndex, targetIndex)
7310
7679
 
7311
7680
  class ShipStepper extends ShipSelectionGroup {
7312
7681
  constructor() {
7313
- super('[value], [step], [routerLinkActive], button, a', 'active');
7682
+ super('[value], [step], [routerLinkActive], button, a', 'active', { hostRole: 'tablist', itemRole: 'tab' });
7314
7683
  this.color = input(null, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
7315
7684
  this.hostClasses = shipComponentClasses('stepper', {
7316
7685
  color: this.color,
@@ -7743,7 +8112,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
7743
8112
 
7744
8113
  class ShipTabs extends ShipSelectionGroup {
7745
8114
  constructor() {
7746
- super('[value], [tab], button, a', 'active');
8115
+ super('[value], [tab], button, a', 'active', { hostRole: 'tablist', itemRole: 'tab' });
7747
8116
  this.id = '--' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 12);
7748
8117
  this.color = input(null, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
7749
8118
  this.variant = input(null, ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
@@ -7985,7 +8354,7 @@ class ShipToggle {
7985
8354
  event.preventDefault();
7986
8355
  }
7987
8356
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ShipToggle, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7988
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipToggle, isStandalone: true, selector: "sh-toggle", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, noInternalInput: { classPropertyName: "noInternalInput", publicName: "noInternalInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, host: { listeners: { "keydown.enter": "onEnter($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() ? \"\" : null" } }, viewQueries: [{ propertyName: "internalInput", first: true, predicate: ["internalInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
8357
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ShipToggle, isStandalone: true, selector: "sh-toggle", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, noInternalInput: { classPropertyName: "noInternalInput", publicName: "noInternalInput", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, host: { listeners: { "keydown.enter": "onEnter($event)", "keydown.space": "onEnter($event)" }, properties: { "class": "hostClasses()", "attr.disabled": "disabled() ? \"\" : null", "attr.role": "noInternalInput() ? \"switch\" : null", "attr.aria-checked": "noInternalInput() ? checked() : null", "attr.tabindex": "noInternalInput() ? (disabled() ? \"-1\" : \"0\") : null" } }, viewQueries: [{ propertyName: "internalInput", first: true, predicate: ["internalInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
7989
8358
  <div class="box">
7990
8359
  <div class="knob"></div>
7991
8360
  </div>
@@ -8029,11 +8398,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
8029
8398
  host: {
8030
8399
  '[class]': 'hostClasses()',
8031
8400
  '[attr.disabled]': 'disabled() ? "" : null',
8401
+ '[attr.role]': 'noInternalInput() ? "switch" : null',
8402
+ '[attr.aria-checked]': 'noInternalInput() ? checked() : null',
8403
+ '[attr.tabindex]': 'noInternalInput() ? (disabled() ? "-1" : "0") : null',
8032
8404
  },
8033
8405
  }]
8034
8406
  }], propDecorators: { internalInput: [{ type: i0.ViewChild, args: ['internalInput', { isSignal: true }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], noInternalInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "noInternalInput", required: false }] }], onEnter: [{
8035
8407
  type: HostListener,
8036
8408
  args: ['keydown.enter', ['$event']]
8409
+ }, {
8410
+ type: HostListener,
8411
+ args: ['keydown.space', ['$event']]
8037
8412
  }] } });
8038
8413
 
8039
8414
  class ShipVirtualScroll {
@@ -8674,6 +9049,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
8674
9049
  args: ['mouseleave', ['$event']]
8675
9050
  }] } });
8676
9051
 
9052
+ const __SHIP_COLORS = ['primary', 'accent', 'warn', 'error', 'success', ''];
9053
+ const __SHIP_SIZES = ['small', 'xsmall', ''];
9054
+ const __SHIP_BUTTON_SIZES = ['small', 'xsmall', ''];
9055
+ const __SHIP_ICON_SIZES = ['small', 'large', ''];
9056
+ const __SHIP_SHEET_VARIANTS = ['simple', 'outlined', 'flat', 'raised', ''];
9057
+ const __SHIP_TYPE_VARIANTS = ['type-a', 'type-b', 'type-c', 'type-d', ''];
9058
+ const __SHIP_TABLE_VARIANTS = ['type-a', 'type-b', ''];
9059
+ const __SHIP_CARD_VARIANTS = ['type-a', 'type-b', 'type-c', ''];
9060
+ const __SHIP_BUTTON_GROUP_VARIANTS = ['type-a', 'type-b', ''];
9061
+ const __SHIP_FORM_FIELD_VARIANTS = ['base', 'horizontal', 'auto-width', 'autosize', ''];
9062
+ const __SHIP_RANGE_SLIDER_VARIANTS = ['simple', 'base', 'thick', 'outlined', 'flat', 'raised', ''];
9063
+
8677
9064
  /*
8678
9065
  * Public API Surface of ship-ui
8679
9066
  */
@@ -8682,5 +9069,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
8682
9069
  * Generated bundle index. Do not edit.
8683
9070
  */
8684
9071
 
8685
- export { SHIP_CONFIG, ShipAccordion, ShipAlert, ShipAlertContainer, ShipAlertModule, ShipAlertService, ShipBlueprint, ShipButton, ShipButtonGroup, ShipCard, ShipCheckbox, ShipChip, ShipColorPicker, ShipColorPickerInput, ShipDatepicker, ShipDatepickerInput, ShipDaterangeInput, ShipDialog, ShipDialogService, ShipDivider, ShipEventCard, ShipFileDragDrop, ShipFileUpload, ShipFormField, ShipFormFieldExperimental, ShipIcon, ShipInputMask, ShipList, ShipMenu, ShipPopover, ShipPreventWheel, ShipProgressBar, ShipRadio, ShipRangeSlider, ShipResize, ShipSelect, ShipSidenav, ShipSort, ShipSortable, ShipSpinner, ShipStepper, ShipStickyColumns, ShipTable, ShipTabs, ShipThemeToggle, ShipToggle, ShipToggleCard, ShipTooltip, ShipTooltipWrapper, ShipVirtualScroll, TEST_NODES, createSortableManager, defaultThemeColors, hslToOklch, hslToRgbExact, hsvToRgbExact, moveIndex, rgbToHex, rgbToHsl, rgbToHsv, rgbToOklch, rgbaToHex8, transferArrayItem, watchHostClass };
9072
+ export { SHIP_CONFIG, ShipAccordion, ShipAlert, ShipAlertContainer, ShipAlertModule, ShipAlertService, ShipBlueprint, ShipButton, ShipButtonGroup, ShipCard, ShipCheckbox, ShipChip, ShipColorPicker, ShipColorPickerInput, ShipDatepicker, ShipDatepickerInput, ShipDaterangeInput, ShipDialog, ShipDialogService, ShipDivider, ShipEventCard, ShipFileDragDrop, ShipFileUpload, ShipFormField, ShipFormFieldExperimental, ShipIcon, ShipInputMask, ShipList, ShipMenu, ShipPopover, ShipPreventWheel, ShipProgressBar, ShipRadio, ShipRangeSlider, ShipResize, ShipSelect, ShipSidenav, ShipSort, ShipSortable, ShipSpinner, ShipStepper, ShipStickyColumns, ShipTable, ShipTabs, ShipThemeToggle, ShipToggle, ShipToggleCard, ShipTooltip, ShipTooltipWrapper, ShipVirtualScroll, TEST_NODES, __SHIP_BUTTON_GROUP_VARIANTS, __SHIP_BUTTON_SIZES, __SHIP_CARD_VARIANTS, __SHIP_COLORS, __SHIP_FORM_FIELD_VARIANTS, __SHIP_ICON_SIZES, __SHIP_RANGE_SLIDER_VARIANTS, __SHIP_SHEET_VARIANTS, __SHIP_SIZES, __SHIP_TABLE_VARIANTS, __SHIP_TYPE_VARIANTS, createSortableManager, defaultThemeColors, hslToOklch, hslToRgbExact, hsvToRgbExact, moveIndex, rgbToHex, rgbToHsl, rgbToHsv, rgbToOklch, rgbaToHex8, transferArrayItem, watchHostClass };
8686
9073
  //# sourceMappingURL=ship-ui-core.mjs.map