@jsekulowicz/ds-components 0.14.0 → 0.16.1

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.
@@ -861,6 +861,40 @@
861
861
  }
862
862
  ]
863
863
  },
864
+ {
865
+ "kind": "javascript-module",
866
+ "path": "src/shared/roving-focus.ts",
867
+ "declarations": [
868
+ {
869
+ "kind": "function",
870
+ "name": "resolveRovingTarget",
871
+ "return": {
872
+ "type": {
873
+ "text": "number | null"
874
+ }
875
+ },
876
+ "parameters": [
877
+ {
878
+ "name": "{\n key,\n currentIndex,\n count,\n orientation = 'both',\n isDisabled = () => false,\n}",
879
+ "type": {
880
+ "text": "RovingTargetOptions"
881
+ }
882
+ }
883
+ ],
884
+ "description": "Resolve the index a roving-tabindex widget (radiogroup, segmented control,\ntablist…) should move to for a given key. Wraps around the ends and skips\ndisabled entries. Returns `null` when the key isn't a navigation key or no\nenabled target exists, so callers can leave the event untouched."
885
+ }
886
+ ],
887
+ "exports": [
888
+ {
889
+ "kind": "js",
890
+ "name": "resolveRovingTarget",
891
+ "declaration": {
892
+ "name": "resolveRovingTarget",
893
+ "module": "src/shared/roving-focus.ts"
894
+ }
895
+ }
896
+ ]
897
+ },
864
898
  {
865
899
  "kind": "javascript-module",
866
900
  "path": "src/shared/scroll-fade-controller.ts",
@@ -1894,6 +1928,47 @@
1894
1928
  },
1895
1929
  "attribute": "aria-invalid"
1896
1930
  },
1931
+ {
1932
+ "kind": "field",
1933
+ "name": "roleAttr",
1934
+ "type": {
1935
+ "text": "string | undefined"
1936
+ },
1937
+ "attribute": "role"
1938
+ },
1939
+ {
1940
+ "kind": "field",
1941
+ "name": "ariaCheckedAttr",
1942
+ "type": {
1943
+ "text": "string | undefined"
1944
+ },
1945
+ "attribute": "aria-checked"
1946
+ },
1947
+ {
1948
+ "kind": "field",
1949
+ "name": "tabIndexAttr",
1950
+ "type": {
1951
+ "text": "number | undefined"
1952
+ }
1953
+ },
1954
+ {
1955
+ "kind": "method",
1956
+ "name": "focus",
1957
+ "return": {
1958
+ "type": {
1959
+ "text": "void"
1960
+ }
1961
+ },
1962
+ "parameters": [
1963
+ {
1964
+ "name": "options",
1965
+ "optional": true,
1966
+ "type": {
1967
+ "text": "FocusOptions"
1968
+ }
1969
+ }
1970
+ ]
1971
+ },
1897
1972
  {
1898
1973
  "kind": "field",
1899
1974
  "name": "#handleClick",
@@ -2018,6 +2093,20 @@
2018
2093
  "text": "string | undefined"
2019
2094
  },
2020
2095
  "fieldName": "ariaInvalidAttr"
2096
+ },
2097
+ {
2098
+ "name": "role",
2099
+ "type": {
2100
+ "text": "string | undefined"
2101
+ },
2102
+ "fieldName": "roleAttr"
2103
+ },
2104
+ {
2105
+ "name": "aria-checked",
2106
+ "type": {
2107
+ "text": "string | undefined"
2108
+ },
2109
+ "fieldName": "ariaCheckedAttr"
2021
2110
  }
2022
2111
  ],
2023
2112
  "superclass": {
@@ -4568,6 +4657,33 @@
4568
4657
  "default": "''",
4569
4658
  "attribute": "radioValue"
4570
4659
  },
4660
+ {
4661
+ "kind": "field",
4662
+ "name": "tabStop",
4663
+ "type": {
4664
+ "text": "boolean"
4665
+ },
4666
+ "default": "true",
4667
+ "attribute": "tab-stop"
4668
+ },
4669
+ {
4670
+ "kind": "method",
4671
+ "name": "focus",
4672
+ "return": {
4673
+ "type": {
4674
+ "text": "void"
4675
+ }
4676
+ },
4677
+ "parameters": [
4678
+ {
4679
+ "name": "options",
4680
+ "optional": true,
4681
+ "type": {
4682
+ "text": "FocusOptions"
4683
+ }
4684
+ }
4685
+ ]
4686
+ },
4571
4687
  {
4572
4688
  "kind": "method",
4573
4689
  "name": "#escapeName",
@@ -4634,6 +4750,14 @@
4634
4750
  },
4635
4751
  "default": "''",
4636
4752
  "fieldName": "radioValue"
4753
+ },
4754
+ {
4755
+ "name": "tab-stop",
4756
+ "type": {
4757
+ "text": "boolean"
4758
+ },
4759
+ "default": "true",
4760
+ "fieldName": "tabStop"
4637
4761
  }
4638
4762
  ],
4639
4763
  "mixins": [
@@ -4816,11 +4940,39 @@
4816
4940
  "name": "#onSlotChange",
4817
4941
  "privacy": "private"
4818
4942
  },
4943
+ {
4944
+ "kind": "method",
4945
+ "name": "#radioValueOf",
4946
+ "privacy": "private",
4947
+ "return": {
4948
+ "type": {
4949
+ "text": "string"
4950
+ }
4951
+ },
4952
+ "parameters": [
4953
+ {
4954
+ "name": "radio",
4955
+ "type": {
4956
+ "text": "RadioEl"
4957
+ }
4958
+ }
4959
+ ]
4960
+ },
4961
+ {
4962
+ "kind": "field",
4963
+ "name": "#isRadioDisabledAt",
4964
+ "privacy": "private"
4965
+ },
4819
4966
  {
4820
4967
  "kind": "field",
4821
4968
  "name": "#wireRadios",
4822
4969
  "privacy": "private"
4823
4970
  },
4971
+ {
4972
+ "kind": "field",
4973
+ "name": "#onKeydown",
4974
+ "privacy": "private"
4975
+ },
4824
4976
  {
4825
4977
  "kind": "field",
4826
4978
  "name": "#onRadioChange",
@@ -5468,7 +5620,7 @@
5468
5620
  {
5469
5621
  "kind": "variable",
5470
5622
  "name": "segmentedControlStyles",
5471
- "default": "css` :host { display: inline-flex; max-width: 100%; } :host([disabled]) { cursor: not-allowed; opacity: 0.6; } .group { display: inline-flex; align-items: stretch; gap: var(--ds-space-1); padding: var(--ds-space-1); background: var(--ds-color-bg-subtle); border: 1px solid var(--ds-color-border-subtle); border-radius: var(--ds-radius-sm); max-width: 100%; } .segment { display: inline-flex; align-items: center; justify-content: center; gap: var(--ds-space-2); min-width: 0; padding: var(--ds-space-2) var(--ds-space-3); border: 0; background: transparent; color: var(--ds-color-fg-muted); font-family: var(--ds-font-body); font-size: var(--ds-font-size-sm); font-weight: var(--ds-font-weight-medium); line-height: 1; white-space: nowrap; border-radius: var(--ds-radius-sm); cursor: pointer; transition: background var(--ds-duration-fast) var(--ds-easing-standard), color var(--ds-duration-fast) var(--ds-easing-standard), box-shadow var(--ds-duration-fast) var(--ds-easing-standard); } .segment:hover:not([disabled]):not([aria-checked='true']) { color: var(--ds-color-fg); } .segment[aria-checked='true'] { background: var(--ds-color-bg); color: var(--ds-color-fg); box-shadow: var(--ds-shadow-sm); } .segment:focus-visible { outline: none; box-shadow: var(--ds-shadow-focus); } .segment[disabled] { cursor: not-allowed; opacity: 0.5; } .label { overflow: hidden; text-overflow: ellipsis; } `"
5623
+ "default": "css` :host { display: inline-flex; flex-direction: column; gap: var(--ds-space-1); max-width: 100%; } :host([disabled]) { cursor: not-allowed; opacity: 0.6; } .group { /* Equal columns that all size to the widest segment: with a shrink-to-fit track, equal 1fr columns each resolve to the widest cell's content, so no segment ends up narrower than its label needs. When the host is given an explicit width they simply share it evenly. */ display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; /* The track colour shows through the 1px padding and gaps as a hairline frame and dividers between the otherwise borderless segments. */ gap: 1px; padding: 1px; background: var(--ds-color-border-subtle); border-radius: var(--ds-radius-sm); max-width: 100%; } .segment { min-width: 0; } /* Lift the focused segment above its neighbours so the full focus ring is visible instead of being painted over by the adjacent segment. */ .segment:focus-within { position: relative; z-index: 1; } /* Give unselected segments a surface that's distinct from the track so each option reads as its own tile; the selected one keeps the accent fill from the primary button variant. Drop the button min-width floor so the grid drives sizing. */ .segment::part(button) { min-width: 0; border-radius: calc(var(--ds-radius-sm) - 1px); } .segment[variant='ghost']::part(button) { background: var(--ds-color-bg); } .segment[variant='ghost']::part(button):hover { background: var(--ds-color-bg-subtle); } /* Square off the inner edges so the row reads as one connected control, rounding only the outer corners of the first and last segments. */ .segment:first-child:not(:last-child)::part(button) { border-top-right-radius: 0; border-bottom-right-radius: 0; } .segment:last-child:not(:first-child)::part(button) { border-top-left-radius: 0; border-bottom-left-radius: 0; } .segment:not(:first-child):not(:last-child)::part(button) { border-radius: 0; } `"
5472
5624
  }
5473
5625
  ],
5474
5626
  "exports": [
@@ -5510,6 +5662,15 @@
5510
5662
  "default": "''",
5511
5663
  "attribute": "label"
5512
5664
  },
5665
+ {
5666
+ "kind": "field",
5667
+ "name": "description",
5668
+ "type": {
5669
+ "text": "string"
5670
+ },
5671
+ "default": "''",
5672
+ "attribute": "description"
5673
+ },
5513
5674
  {
5514
5675
  "kind": "field",
5515
5676
  "name": "value",
@@ -5538,6 +5699,15 @@
5538
5699
  "attribute": "disabled",
5539
5700
  "reflects": true
5540
5701
  },
5702
+ {
5703
+ "kind": "field",
5704
+ "name": "#tabStopIndex",
5705
+ "privacy": "private",
5706
+ "type": {
5707
+ "text": "number"
5708
+ },
5709
+ "readonly": true
5710
+ },
5541
5711
  {
5542
5712
  "kind": "method",
5543
5713
  "name": "#select",
@@ -5555,6 +5725,53 @@
5555
5725
  }
5556
5726
  }
5557
5727
  ]
5728
+ },
5729
+ {
5730
+ "kind": "method",
5731
+ "name": "#focusSegment",
5732
+ "privacy": "private",
5733
+ "return": {
5734
+ "type": {
5735
+ "text": "void"
5736
+ }
5737
+ },
5738
+ "parameters": [
5739
+ {
5740
+ "name": "index",
5741
+ "type": {
5742
+ "text": "number"
5743
+ }
5744
+ }
5745
+ ]
5746
+ },
5747
+ {
5748
+ "kind": "field",
5749
+ "name": "#onKeydown",
5750
+ "privacy": "private"
5751
+ },
5752
+ {
5753
+ "kind": "method",
5754
+ "name": "#renderSegment",
5755
+ "privacy": "private",
5756
+ "return": {
5757
+ "type": {
5758
+ "text": "TemplateResult"
5759
+ }
5760
+ },
5761
+ "parameters": [
5762
+ {
5763
+ "name": "option",
5764
+ "type": {
5765
+ "text": "SegmentedControlOption"
5766
+ }
5767
+ },
5768
+ {
5769
+ "name": "index",
5770
+ "type": {
5771
+ "text": "number"
5772
+ }
5773
+ }
5774
+ ]
5558
5775
  }
5559
5776
  ],
5560
5777
  "events": [
@@ -5572,6 +5789,14 @@
5572
5789
  "default": "''",
5573
5790
  "fieldName": "label"
5574
5791
  },
5792
+ {
5793
+ "name": "description",
5794
+ "type": {
5795
+ "text": "string"
5796
+ },
5797
+ "default": "''",
5798
+ "fieldName": "description"
5799
+ },
5575
5800
  {
5576
5801
  "name": "value",
5577
5802
  "type": {
@@ -28,6 +28,10 @@ export declare class DsButton extends DsElement {
28
28
  ariaExpandedAttr?: string;
29
29
  ariaHasPopupAttr?: string;
30
30
  ariaInvalidAttr?: string;
31
+ roleAttr?: string;
32
+ ariaCheckedAttr?: string;
33
+ tabIndexAttr?: number;
34
+ focus(options?: FocusOptions): void;
31
35
  render(): TemplateResult;
32
36
  }
33
37
  //# sourceMappingURL=button.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/atoms/button/button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AACzE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC5C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEvD;;;;;;;;;GASG;AACH,qBAAa,QAAS,SAAQ,SAAS;;IACrC,OAAgB,MAAM,4BAAuC;IAEhC,OAAO,EAAE,aAAa,CAAa;IACnC,IAAI,EAAE,UAAU,CAAQ;IACxB,IAAI,EAAE,UAAU,CAAY;IACb,QAAQ,UAAS;IACjB,OAAO,UAAS;IACS,SAAS,UAAS;IAC3C,MAAM,UAAS;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACe,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IA+BzD,MAAM,IAAI,cAAc;CAkClC"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/atoms/button/button.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AACzE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAC5C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEvD;;;;;;;;;GASG;AACH,qBAAa,QAAS,SAAQ,SAAS;;IACrC,OAAgB,MAAM,4BAAuC;IAEhC,OAAO,EAAE,aAAa,CAAa;IACnC,IAAI,EAAE,UAAU,CAAQ;IACxB,IAAI,EAAE,UAAU,CAAY;IACb,QAAQ,UAAS;IACjB,OAAO,UAAS;IACS,SAAS,UAAS;IAC3C,MAAM,UAAS;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACe,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IAKjC,QAAQ,CAAC,EAAE,MAAM,CAAC;IACV,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IAE7C,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAiCnC,MAAM,IAAI,cAAc;CAqClC"}
@@ -41,6 +41,9 @@ export class DsButton extends DsElement {
41
41
  };
42
42
  }
43
43
  static { this.styles = [...DsElement.styles, buttonStyles]; }
44
+ focus(options) {
45
+ this.renderRoot.querySelector('button')?.focus(options);
46
+ }
44
47
  #handleClick;
45
48
  #submitHostForm() {
46
49
  const form = this.closest('form') ?? this.#findShadowForm();
@@ -64,8 +67,11 @@ export class DsButton extends DsElement {
64
67
  part="button"
65
68
  class="btn ds-focus-ring"
66
69
  type=${this.type}
70
+ role=${this.roleAttr ?? nothing}
71
+ tabindex=${this.tabIndexAttr ?? nothing}
67
72
  aria-disabled=${this.disabled || this.loading ? 'true' : 'false'}
68
73
  aria-busy=${this.loading ? 'true' : 'false'}
74
+ aria-checked=${this.ariaCheckedAttr ?? nothing}
69
75
  aria-controls=${this.ariaControlsAttr ?? nothing}
70
76
  aria-expanded=${this.ariaExpandedAttr ?? nothing}
71
77
  aria-haspopup=${this.ariaHasPopupAttr ?? nothing}
@@ -129,4 +135,13 @@ __decorate([
129
135
  __decorate([
130
136
  property({ attribute: 'aria-invalid' })
131
137
  ], DsButton.prototype, "ariaInvalidAttr", void 0);
138
+ __decorate([
139
+ property({ attribute: 'role' })
140
+ ], DsButton.prototype, "roleAttr", void 0);
141
+ __decorate([
142
+ property({ attribute: 'aria-checked' })
143
+ ], DsButton.prototype, "ariaCheckedAttr", void 0);
144
+ __decorate([
145
+ property({ attribute: false })
146
+ ], DsButton.prototype, "tabIndexAttr", void 0);
132
147
  //# sourceMappingURL=button.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../src/atoms/button/button.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../src/atoms/button/button.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,8 @@ export declare class DsRadio extends DsRadio_base {
12
12
  static styles: import("lit").CSSResult[];
13
13
  checked: boolean;
14
14
  radioValue: string;
15
+ tabStop: boolean;
16
+ focus(options?: FocusOptions): void;
15
17
  willUpdate(changed: PropertyValues): void;
16
18
  render(): TemplateResult;
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"radio.d.ts","sourceRoot":"","sources":["../../../src/atoms/radio/radio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAErE,OAAO,EAAE,SAAS,EAAoB,MAAM,sBAAsB,CAAC;;AAGnE;;;;;GAKG;AACH,qBAAa,OAAQ,SAAQ,YAA2B;;IACtD,OAAgB,MAAM,4BAAsC;IAEhB,OAAO,UAAS;IAChD,UAAU,SAAM;IAEnB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAiDzC,MAAM,IAAI,cAAc;CAclC"}
1
+ {"version":3,"file":"radio.d.ts","sourceRoot":"","sources":["../../../src/atoms/radio/radio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAErE,OAAO,EAAE,SAAS,EAAoB,MAAM,sBAAsB,CAAC;;AAGnE;;;;;GAKG;AACH,qBAAa,OAAQ,SAAQ,YAA2B;;IACtD,OAAgB,MAAM,4BAAsC;IAEhB,OAAO,UAAS;IAChD,UAAU,SAAM;IAIwB,OAAO,UAAQ;IAE1D,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAInC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAiDzC,MAAM,IAAI,cAAc;CAelC"}
@@ -19,6 +19,10 @@ export class DsRadio extends FormControlMixin(DsElement) {
19
19
  super(...arguments);
20
20
  this.checked = false;
21
21
  this.radioValue = '';
22
+ // Roving tabindex within a ds-radio-group: only the active radio stays in the
23
+ // page tab order, the rest are reachable with arrow keys. Defaults to a
24
+ // normal tab stop so a standalone radio still works on its own.
25
+ this.tabStop = true;
22
26
  this.#onInputClick = (event) => {
23
27
  if (this.disabled) {
24
28
  event.preventDefault();
@@ -40,6 +44,9 @@ export class DsRadio extends FormControlMixin(DsElement) {
40
44
  };
41
45
  }
42
46
  static { this.styles = [...DsElement.styles, radioStyles]; }
47
+ focus(options) {
48
+ this.renderRoot.querySelector('input')?.focus(options);
49
+ }
43
50
  willUpdate(changed) {
44
51
  if (changed.has('checked')) {
45
52
  this.value = this.checked ? this.radioValue || 'on' : null;
@@ -74,6 +81,7 @@ export class DsRadio extends FormControlMixin(DsElement) {
74
81
  name=${this.name || ''}
75
82
  .checked=${this.checked}
76
83
  value=${this.radioValue}
84
+ tabindex=${this.tabStop ? '0' : '-1'}
77
85
  ?required=${this.required}
78
86
  @click=${this.#onInputClick}
79
87
  />
@@ -88,4 +96,7 @@ __decorate([
88
96
  __decorate([
89
97
  property()
90
98
  ], DsRadio.prototype, "radioValue", void 0);
99
+ __decorate([
100
+ property({ type: Boolean, attribute: 'tab-stop' })
101
+ ], DsRadio.prototype, "tabStop", void 0);
91
102
  //# sourceMappingURL=radio.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"radio.js","sourceRoot":"","sources":["../../../src/atoms/radio/radio.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"radio.js","sourceRoot":"","sources":["../../../src/atoms/radio/radio.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAA4C,MAAM,KAAK,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,OAAO,OAAQ,SAAQ,gBAAgB,CAAC,SAAS,CAAC;IAAxD;;QAG8C,YAAO,GAAG,KAAK,CAAC;QAChD,eAAU,GAAG,EAAE,CAAC;QAC5B,8EAA8E;QAC9E,wEAAwE;QACxE,gEAAgE;QACZ,YAAO,GAAG,IAAI,CAAC;QAiCnE,kBAAa,GAAG,CAAC,KAAY,EAAQ,EAAE;YACrC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,KAAK,CAAC,cAAc,EAAE,CAAC;YACzB,CAAC;QACH,CAAC,CAAC;QAEF,YAAO,GAAG,GAAS,EAAE;YACnB,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClC,OAAO;YACT,CAAC;YACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACjE,CAAC,CAAC;QAEF,WAAM,GAAG,CAAC,KAAoB,EAAQ,EAAE;YACtC,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;gBAC/C,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;IAiBJ,CAAC;aA7EiB,WAAM,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,WAAW,CAAC,AAArC,CAAsC;IASnD,KAAK,CAAC,OAAsB;QACnC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAmB,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3E,CAAC;IAEQ,UAAU,CAAC,OAAuB;QACzC,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,WAAW,CAAC,KAAa;QACvB,IAAI,OAAO,GAAG,KAAK,WAAW,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACnE,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,KAAK,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,gBAAgB;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QAC9C,IAAI,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,YAAY,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,YAAY,QAAQ,CAAC,EAAE,CAAC;YACtG,OAAO;QACT,CAAC;QACD,MAAM,QAAQ,GAAG,kBAAkB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QACnE,MAAM,QAAQ,GAAI,KAAyC,CAAC,gBAAgB,CAAU,QAAQ,CAAC,CAAC;QAChG,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3B,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,aAAa,CAIX;IAEF,OAAO,CAOL;IAEF,MAAM,CAKJ;IAEO,MAAM;QACb,OAAO,IAAI,CAAA,iBAAiB,IAAI,CAAC,OAAO,aAAa,IAAI,CAAC,MAAM;;;eAGrD,IAAI,CAAC,IAAI,IAAI,EAAE;mBACX,IAAI,CAAC,OAAO;gBACf,IAAI,CAAC,UAAU;mBACZ,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI;oBACxB,IAAI,CAAC,QAAQ;iBAChB,IAAI,CAAC,aAAa;;;;aAItB,CAAC;IACZ,CAAC;;AA1E2C;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;wCAAiB;AAChD;IAAX,QAAQ,EAAE;2CAAiB;AAIwB;IAAnD,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;wCAAgB"}
@@ -1 +1 @@
1
- {"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../../src/atoms/radio-group/radio-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAMjD;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,SAAS;;IACzC,OAAgB,MAAM,4BAA4D;IAEtE,KAAK,SAAM;IACX,IAAI,SAAM;IACV,WAAW,SAAM;IACjB,KAAK,SAAM;IACX,KAAK,SAAM;IACqB,QAAQ,UAAS;IACjB,QAAQ,UAAS;IACjB,OAAO,UAAS;IAEX,OAAO,CAAC,OAAO,CAAa;IAEpE,iBAAiB,IAAI,IAAI;IAQzB,oBAAoB,IAAI,IAAI;IAK5B,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA2C5C,MAAM,IAAI,cAAc;CAclC"}
1
+ {"version":3,"file":"radio-group.d.ts","sourceRoot":"","sources":["../../../src/atoms/radio-group/radio-group.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAYjD;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,SAAS;;IACzC,OAAgB,MAAM,4BAA4D;IAEtE,KAAK,SAAM;IACX,IAAI,SAAM;IACV,WAAW,SAAM;IACjB,KAAK,SAAM;IACX,KAAK,SAAM;IACqB,QAAQ,UAAS;IACjB,QAAQ,UAAS;IACjB,OAAO,UAAS;IAEX,OAAO,CAAC,OAAO,CAAa;IAEpE,iBAAiB,IAAI,IAAI;IAQzB,oBAAoB,IAAI,IAAI;IAK5B,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAyF5C,MAAM,IAAI,cAAc;CAclC"}
@@ -8,6 +8,7 @@ import { html, nothing } from 'lit';
8
8
  import { property, queryAssignedElements } from 'lit/decorators.js';
9
9
  import { DsElement } from '@jsekulowicz/ds-core';
10
10
  import { formFieldStyles, renderSubtext } from '../../shared/form-field.js';
11
+ import { resolveRovingTarget } from '../../shared/roving-focus.js';
11
12
  import { radioGroupStyles } from './radio-group.styles.js';
12
13
  /**
13
14
  * @tag ds-radio-group
@@ -29,8 +30,18 @@ export class DsRadioGroup extends DsElement {
29
30
  this.#onSlotChange = () => {
30
31
  this.#wireRadios(this.value !== '');
31
32
  };
33
+ this.#isRadioDisabledAt = (index) => {
34
+ const radio = this._radios[index];
35
+ return radio ? radio.hasAttribute('disabled') : true;
36
+ };
32
37
  this.#wireRadios = (syncChecked) => {
33
- this._radios.forEach(radio => {
38
+ const radios = this._radios;
39
+ const selectedIndex = radios.findIndex(radio => this.#radioValueOf(radio) === this.value);
40
+ const firstEnabled = radios.findIndex(radio => !radio.hasAttribute('disabled'));
41
+ // Exactly one radio stays in the tab order: the selected one, or the first
42
+ // enabled radio when nothing is selected yet (roving tabindex).
43
+ const tabStopIndex = selectedIndex >= 0 ? selectedIndex : firstEnabled;
44
+ radios.forEach((radio, index) => {
34
45
  if (this.name)
35
46
  radio.setAttribute('name', this.name);
36
47
  if (this.required) {
@@ -45,9 +56,9 @@ export class DsRadioGroup extends DsElement {
45
56
  else {
46
57
  radio.removeAttribute('disabled');
47
58
  }
59
+ radio.tabStop = index === tabStopIndex;
48
60
  if (syncChecked) {
49
- const rv = radio.radioValue ?? radio.getAttribute('radiovalue') ?? '';
50
- if (rv === this.value) {
61
+ if (this.#radioValueOf(radio) === this.value) {
51
62
  radio.setAttribute('checked', '');
52
63
  }
53
64
  else {
@@ -56,6 +67,34 @@ export class DsRadioGroup extends DsElement {
56
67
  }
57
68
  });
58
69
  };
70
+ this.#onKeydown = (event) => {
71
+ if (this.disabled) {
72
+ return;
73
+ }
74
+ const radios = this._radios;
75
+ const target = resolveRovingTarget({
76
+ key: event.key,
77
+ currentIndex: radios.findIndex(radio => this.#radioValueOf(radio) === this.value),
78
+ count: radios.length,
79
+ isDisabled: this.#isRadioDisabledAt,
80
+ });
81
+ if (target === null) {
82
+ return;
83
+ }
84
+ const radio = radios[target];
85
+ if (!radio) {
86
+ return;
87
+ }
88
+ event.preventDefault();
89
+ // Selection follows focus, as the radiogroup pattern prescribes.
90
+ const value = this.#radioValueOf(radio);
91
+ if (value !== this.value) {
92
+ this.value = value;
93
+ this.invalid = false;
94
+ this.dispatchEvent(new CustomEvent('ds-change', { bubbles: true, composed: true, detail: { value } }));
95
+ }
96
+ void this.updateComplete.then(() => radio.focus());
97
+ };
59
98
  this.#onRadioChange = (event) => {
60
99
  if (event.target === this) {
61
100
  return;
@@ -83,11 +122,16 @@ export class DsRadioGroup extends DsElement {
83
122
  this.#wireRadios(changed.has('value'));
84
123
  }
85
124
  #onSlotChange;
125
+ #radioValueOf(radio) {
126
+ return radio.radioValue ?? radio.getAttribute('radiovalue') ?? '';
127
+ }
128
+ #isRadioDisabledAt;
86
129
  #wireRadios;
130
+ #onKeydown;
87
131
  #onRadioChange;
88
132
  render() {
89
133
  return html `
90
- <fieldset class="fieldset" part="fieldset">
134
+ <fieldset class="fieldset" part="fieldset" @keydown=${this.#onKeydown}>
91
135
  <legend class="label" part="legend">
92
136
  ${this.label}
93
137
  ${this.required ? html `<span class="required" aria-hidden="true"> *</span>` : nothing}
@@ -1 +1 @@
1
- {"version":3,"file":"radio-group.js","sourceRoot":"","sources":["../../../src/atoms/radio-group/radio-group.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"radio-group.js","sourceRoot":"","sources":["../../../src/atoms/radio-group/radio-group.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { type TemplateResult } from 'lit';
2
2
  import { DsElement } from '@jsekulowicz/ds-core';
3
+ import '../button/define.js';
3
4
  import '../icon/define.js';
4
5
  export interface SegmentedControlOption {
5
6
  value: string;
@@ -21,6 +22,7 @@ export declare class DsSegmentedControl extends DsElement {
21
22
  #private;
22
23
  static styles: import("lit").CSSResult[];
23
24
  label: string;
25
+ description: string;
24
26
  value: string;
25
27
  options: SegmentedControlOption[];
26
28
  disabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.d.ts","sourceRoot":"","sources":["../../../src/atoms/segmented-control/segmented-control.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,OAAO,mBAAmB,CAAC;AAE3B,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;;IAC/C,OAAgB,MAAM,4BAAiD;IAE3D,KAAK,SAAM;IACX,KAAK,SAAM;IACI,OAAO,EAAE,sBAAsB,EAAE,CAAM;IACtB,QAAQ,UAAS;IAEpD,iBAAiB,IAAI,IAAI;IAiBzB,MAAM,IAAI,cAAc;CAyBlC"}
1
+ {"version":3,"file":"segmented-control.d.ts","sourceRoot":"","sources":["../../../src/atoms/segmented-control/segmented-control.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,OAAO,qBAAqB,CAAC;AAC7B,OAAO,mBAAmB,CAAC;AAE3B,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;;IAC/C,OAAgB,MAAM,4BAAkE;IAE5E,KAAK,SAAM;IACX,WAAW,SAAM;IACjB,KAAK,SAAM;IACI,OAAO,EAAE,sBAAsB,EAAE,CAAM;IACtB,QAAQ,UAAS;IAEpD,iBAAiB,IAAI,IAAI;IA8EzB,MAAM,IAAI,cAAc;CAgBlC"}
@@ -7,7 +7,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { html, nothing } from 'lit';
8
8
  import { property } from 'lit/decorators.js';
9
9
  import { DsElement } from '@jsekulowicz/ds-core';
10
+ import { formFieldStyles, renderFieldLabel, renderSubtext } from '../../shared/form-field.js';
11
+ import { resolveRovingTarget } from '../../shared/roving-focus.js';
10
12
  import { segmentedControlStyles } from './segmented-control.styles.js';
13
+ import '../button/define.js';
11
14
  import '../icon/define.js';
12
15
  /**
13
16
  * @tag ds-segmented-control
@@ -22,17 +25,49 @@ export class DsSegmentedControl extends DsElement {
22
25
  constructor() {
23
26
  super(...arguments);
24
27
  this.label = '';
28
+ this.description = '';
25
29
  this.value = '';
26
30
  this.options = [];
27
31
  this.disabled = false;
32
+ this.#onKeydown = (event) => {
33
+ if (this.disabled) {
34
+ return;
35
+ }
36
+ const target = resolveRovingTarget({
37
+ key: event.key,
38
+ currentIndex: this.#tabStopIndex,
39
+ count: this.options.length,
40
+ isDisabled: index => this.options[index]?.disabled === true,
41
+ });
42
+ if (target === null) {
43
+ return;
44
+ }
45
+ const option = this.options[target];
46
+ if (!option) {
47
+ return;
48
+ }
49
+ event.preventDefault();
50
+ // Selection follows focus, as the radiogroup pattern prescribes.
51
+ this.#select(option);
52
+ void this.updateComplete.then(() => this.#focusSegment(target));
53
+ };
28
54
  }
29
- static { this.styles = [...DsElement.styles, segmentedControlStyles]; }
55
+ static { this.styles = [...DsElement.styles, formFieldStyles, segmentedControlStyles]; }
30
56
  connectedCallback() {
31
57
  super.connectedCallback();
32
58
  if (!this.label) {
33
59
  console.warn('<ds-segmented-control>: the `label` property is required for accessibility.');
34
60
  }
35
61
  }
62
+ // The single tab stop: the selected option, or the first enabled one when
63
+ // nothing is selected yet. Arrow keys move focus (and selection) from here.
64
+ get #tabStopIndex() {
65
+ const selected = this.options.findIndex(option => option.value === this.value);
66
+ if (selected >= 0) {
67
+ return selected;
68
+ }
69
+ return this.options.findIndex(option => !option.disabled);
70
+ }
36
71
  #select(option) {
37
72
  if (this.disabled || option.disabled || option.value === this.value) {
38
73
  return;
@@ -40,35 +75,56 @@ export class DsSegmentedControl extends DsElement {
40
75
  this.value = option.value;
41
76
  this.emit('ds-change', { detail: { value: option.value } });
42
77
  }
78
+ #focusSegment(index) {
79
+ const segments = this.renderRoot.querySelectorAll('.segment');
80
+ segments[index]?.focus();
81
+ }
82
+ #onKeydown;
83
+ #renderSegment(option, index) {
84
+ const selected = option.value === this.value;
85
+ return html `
86
+ <ds-button
87
+ class="segment"
88
+ part="segment"
89
+ size="sm"
90
+ variant=${selected ? 'primary' : 'ghost'}
91
+ full-width
92
+ .roleAttr=${'radio'}
93
+ .ariaCheckedAttr=${selected ? 'true' : 'false'}
94
+ .tabIndexAttr=${index === this.#tabStopIndex ? 0 : -1}
95
+ ?disabled=${this.disabled || option.disabled}
96
+ @ds-click=${() => this.#select(option)}
97
+ >
98
+ ${option.icon
99
+ ? html `<ds-icon slot="leading" name=${option.icon} size="sm"></ds-icon>`
100
+ : nothing}
101
+ ${option.label}
102
+ </ds-button>
103
+ `;
104
+ }
43
105
  render() {
44
106
  return html `
45
- <div class="group" role="radiogroup" aria-label=${this.label} part="group">
46
- ${this.options.map(option => {
47
- const selected = option.value === this.value;
48
- return html `
49
- <button
50
- type="button"
51
- class="segment"
52
- part="segment"
53
- role="radio"
54
- aria-checked=${selected ? 'true' : 'false'}
55
- ?disabled=${this.disabled || option.disabled}
56
- @click=${() => this.#select(option)}
57
- >
58
- ${option.icon
59
- ? html `<ds-icon name=${option.icon} size="md" part="icon"></ds-icon>`
60
- : nothing}
61
- <span class="label">${option.label}</span>
62
- </button>
63
- `;
64
- })}
107
+ ${this.label ? renderFieldLabel(this.label, false, 'group') : nothing}
108
+ <div
109
+ class="group"
110
+ id="group"
111
+ role="radiogroup"
112
+ aria-label=${this.label}
113
+ part="group"
114
+ @keydown=${this.#onKeydown}
115
+ >
116
+ ${this.options.map((option, index) => this.#renderSegment(option, index))}
65
117
  </div>
118
+ ${renderSubtext(this.description, '', false)}
66
119
  `;
67
120
  }
68
121
  }
69
122
  __decorate([
70
123
  property()
71
124
  ], DsSegmentedControl.prototype, "label", void 0);
125
+ __decorate([
126
+ property()
127
+ ], DsSegmentedControl.prototype, "description", void 0);
72
128
  __decorate([
73
129
  property()
74
130
  ], DsSegmentedControl.prototype, "value", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.js","sourceRoot":"","sources":["../../../src/atoms/segmented-control/segmented-control.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAuB,MAAM,KAAK,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,mBAAmB,CAAC;AAU3B;;;;;;;;GAQG;AACH,MAAM,OAAO,kBAAmB,SAAQ,SAAS;IAAjD;;QAGc,UAAK,GAAG,EAAE,CAAC;QACX,UAAK,GAAG,EAAE,CAAC;QACI,YAAO,GAA6B,EAAE,CAAC;QACtB,aAAQ,GAAG,KAAK,CAAC;IA4C/D,CAAC;aAjDiB,WAAM,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,sBAAsB,CAAC,AAAhD,CAAiD;IAO9D,iBAAiB;QACxB,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,IAAI,CACV,6EAA6E,CAC9E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,CAAC,MAA8B;QACpC,IAAI,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACpE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAEQ,MAAM;QACb,OAAO,IAAI,CAAA;wDACyC,IAAI,CAAC,KAAK;UACxD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;YAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC;YAC7C,OAAO,IAAI,CAAA;;;;;;6BAMQ,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;0BAC9B,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ;uBACnC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;;gBAEjC,MAAM,CAAC,IAAI;gBACX,CAAC,CAAC,IAAI,CAAA,iBAAiB,MAAM,CAAC,IAAI,mCAAmC;gBACrE,CAAC,CAAC,OAAO;oCACW,MAAM,CAAC,KAAK;;WAErC,CAAC;QACJ,CAAC,CAAC;;KAEL,CAAC;IACJ,CAAC;;AA9CW;IAAX,QAAQ,EAAE;iDAAY;AACX;IAAX,QAAQ,EAAE;iDAAY;AACI;IAA1B,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;mDAAwC;AACtB;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;oDAAkB"}
1
+ {"version":3,"file":"segmented-control.js","sourceRoot":"","sources":["../../../src/atoms/segmented-control/segmented-control.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.styles.d.ts","sourceRoot":"","sources":["../../../src/atoms/segmented-control/segmented-control.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB,yBA6DlC,CAAC"}
1
+ {"version":3,"file":"segmented-control.styles.d.ts","sourceRoot":"","sources":["../../../src/atoms/segmented-control/segmented-control.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,sBAAsB,yBA+DlC,CAAC"}
@@ -2,6 +2,8 @@ import { css } from 'lit';
2
2
  export const segmentedControlStyles = css `
3
3
  :host {
4
4
  display: inline-flex;
5
+ flex-direction: column;
6
+ gap: var(--ds-space-1);
5
7
  max-width: 100%;
6
8
  }
7
9
  :host([disabled]) {
@@ -9,56 +11,56 @@ export const segmentedControlStyles = css `
9
11
  opacity: 0.6;
10
12
  }
11
13
  .group {
12
- display: inline-flex;
13
- align-items: stretch;
14
- gap: var(--ds-space-1);
15
- padding: var(--ds-space-1);
16
- background: var(--ds-color-bg-subtle);
17
- border: 1px solid var(--ds-color-border-subtle);
14
+ /* Equal columns that all size to the widest segment: with a shrink-to-fit
15
+ track, equal 1fr columns each resolve to the widest cell's content, so
16
+ no segment ends up narrower than its label needs. When the host is given
17
+ an explicit width they simply share it evenly. */
18
+ display: grid;
19
+ grid-auto-flow: column;
20
+ grid-auto-columns: 1fr;
21
+ /* The track colour shows through the 1px padding and gaps as a hairline
22
+ frame and dividers between the otherwise borderless segments. */
23
+ gap: 1px;
24
+ padding: 1px;
25
+ background: var(--ds-color-border-subtle);
18
26
  border-radius: var(--ds-radius-sm);
19
27
  max-width: 100%;
20
28
  }
21
29
  .segment {
22
- display: inline-flex;
23
- align-items: center;
24
- justify-content: center;
25
- gap: var(--ds-space-2);
26
30
  min-width: 0;
27
- padding: var(--ds-space-2) var(--ds-space-3);
28
- border: 0;
29
- background: transparent;
30
- color: var(--ds-color-fg-muted);
31
- font-family: var(--ds-font-body);
32
- font-size: var(--ds-font-size-sm);
33
- font-weight: var(--ds-font-weight-medium);
34
- line-height: 1;
35
- white-space: nowrap;
36
- border-radius: var(--ds-radius-sm);
37
- cursor: pointer;
38
- transition:
39
- background var(--ds-duration-fast) var(--ds-easing-standard),
40
- color var(--ds-duration-fast) var(--ds-easing-standard),
41
- box-shadow var(--ds-duration-fast) var(--ds-easing-standard);
42
31
  }
43
- .segment:hover:not([disabled]):not([aria-checked='true']) {
44
- color: var(--ds-color-fg);
32
+ /* Lift the focused segment above its neighbours so the full focus ring is
33
+ visible instead of being painted over by the adjacent segment. */
34
+ .segment:focus-within {
35
+ position: relative;
36
+ z-index: 1;
45
37
  }
46
- .segment[aria-checked='true'] {
38
+ /* Give unselected segments a surface that's distinct from the track so each
39
+ option reads as its own tile; the selected one keeps the accent fill from
40
+ the primary button variant. Drop the button min-width floor so the grid
41
+ drives sizing. */
42
+ .segment::part(button) {
43
+ min-width: 0;
44
+ border-radius: calc(var(--ds-radius-sm) - 1px);
45
+ }
46
+ .segment[variant='ghost']::part(button) {
47
47
  background: var(--ds-color-bg);
48
- color: var(--ds-color-fg);
49
- box-shadow: var(--ds-shadow-sm);
50
48
  }
51
- .segment:focus-visible {
52
- outline: none;
53
- box-shadow: var(--ds-shadow-focus);
49
+ .segment[variant='ghost']::part(button):hover {
50
+ background: var(--ds-color-bg-subtle);
54
51
  }
55
- .segment[disabled] {
56
- cursor: not-allowed;
57
- opacity: 0.5;
52
+ /* Square off the inner edges so the row reads as one connected control,
53
+ rounding only the outer corners of the first and last segments. */
54
+ .segment:first-child:not(:last-child)::part(button) {
55
+ border-top-right-radius: 0;
56
+ border-bottom-right-radius: 0;
57
+ }
58
+ .segment:last-child:not(:first-child)::part(button) {
59
+ border-top-left-radius: 0;
60
+ border-bottom-left-radius: 0;
58
61
  }
59
- .label {
60
- overflow: hidden;
61
- text-overflow: ellipsis;
62
+ .segment:not(:first-child):not(:last-child)::part(button) {
63
+ border-radius: 0;
62
64
  }
63
65
  `;
64
66
  //# sourceMappingURL=segmented-control.styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.styles.js","sourceRoot":"","sources":["../../../src/atoms/segmented-control/segmented-control.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6DxC,CAAC"}
1
+ {"version":3,"file":"segmented-control.styles.js","sourceRoot":"","sources":["../../../src/atoms/segmented-control/segmented-control.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+DxC,CAAC"}
@@ -0,0 +1,19 @@
1
+ export type RovingOrientation = 'horizontal' | 'vertical' | 'both';
2
+ export interface RovingTargetOptions {
3
+ key: string;
4
+ /** Index the navigation starts from; -1 when nothing is focused yet. */
5
+ currentIndex: number;
6
+ count: number;
7
+ /** Which arrow keys participate. Defaults to `both`. */
8
+ orientation?: RovingOrientation;
9
+ /** Skip indices that can't receive selection (e.g. disabled options). */
10
+ isDisabled?: (index: number) => boolean;
11
+ }
12
+ /**
13
+ * Resolve the index a roving-tabindex widget (radiogroup, segmented control,
14
+ * tablist…) should move to for a given key. Wraps around the ends and skips
15
+ * disabled entries. Returns `null` when the key isn't a navigation key or no
16
+ * enabled target exists, so callers can leave the event untouched.
17
+ */
18
+ export declare function resolveRovingTarget({ key, currentIndex, count, orientation, isDisabled, }: RovingTargetOptions): number | null;
19
+ //# sourceMappingURL=roving-focus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roving-focus.d.ts","sourceRoot":"","sources":["../../src/shared/roving-focus.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,yEAAyE;IACzE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CACzC;AAID;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,GAAG,EACH,YAAY,EACZ,KAAK,EACL,WAAoB,EACpB,UAAwB,GACzB,EAAE,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAiCrC"}
@@ -0,0 +1,44 @@
1
+ const wrap = (value, count) => ((value % count) + count) % count;
2
+ /**
3
+ * Resolve the index a roving-tabindex widget (radiogroup, segmented control,
4
+ * tablist…) should move to for a given key. Wraps around the ends and skips
5
+ * disabled entries. Returns `null` when the key isn't a navigation key or no
6
+ * enabled target exists, so callers can leave the event untouched.
7
+ */
8
+ export function resolveRovingTarget({ key, currentIndex, count, orientation = 'both', isDisabled = () => false, }) {
9
+ if (count === 0) {
10
+ return null;
11
+ }
12
+ const horizontal = orientation === 'horizontal' || orientation === 'both';
13
+ const vertical = orientation === 'vertical' || orientation === 'both';
14
+ const forward = (horizontal && key === 'ArrowRight') || (vertical && key === 'ArrowDown');
15
+ const backward = (horizontal && key === 'ArrowLeft') || (vertical && key === 'ArrowUp');
16
+ let from = currentIndex;
17
+ let step;
18
+ if (forward) {
19
+ step = 1;
20
+ }
21
+ else if (backward) {
22
+ step = -1;
23
+ }
24
+ else if (key === 'Home') {
25
+ from = -1;
26
+ step = 1;
27
+ }
28
+ else if (key === 'End') {
29
+ from = count;
30
+ step = -1;
31
+ }
32
+ else {
33
+ return null;
34
+ }
35
+ let index = from;
36
+ for (let i = 0; i < count; i += 1) {
37
+ index = wrap(index + step, count);
38
+ if (!isDisabled(index)) {
39
+ return index;
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ //# sourceMappingURL=roving-focus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roving-focus.js","sourceRoot":"","sources":["../../src/shared/roving-focus.ts"],"names":[],"mappings":"AAaA,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,KAAa,EAAU,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC;AAEzF;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,GAAG,EACH,YAAY,EACZ,KAAK,EACL,WAAW,GAAG,MAAM,EACpB,UAAU,GAAG,GAAG,EAAE,CAAC,KAAK,GACJ;IACpB,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,WAAW,KAAK,YAAY,IAAI,WAAW,KAAK,MAAM,CAAC;IAC1E,MAAM,QAAQ,GAAG,WAAW,KAAK,UAAU,IAAI,WAAW,KAAK,MAAM,CAAC;IACtE,MAAM,OAAO,GAAG,CAAC,UAAU,IAAI,GAAG,KAAK,YAAY,CAAC,IAAI,CAAC,QAAQ,IAAI,GAAG,KAAK,WAAW,CAAC,CAAC;IAC1F,MAAM,QAAQ,GAAG,CAAC,UAAU,IAAI,GAAG,KAAK,WAAW,CAAC,IAAI,CAAC,QAAQ,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC;IAExF,IAAI,IAAI,GAAG,YAAY,CAAC;IACxB,IAAI,IAAY,CAAC;IACjB,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,GAAG,CAAC,CAAC;IACX,CAAC;SAAM,IAAI,QAAQ,EAAE,CAAC;QACpB,IAAI,GAAG,CAAC,CAAC,CAAC;IACZ,CAAC;SAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,CAAC,CAAC;QACV,IAAI,GAAG,CAAC,CAAC;IACX,CAAC;SAAM,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QACzB,IAAI,GAAG,KAAK,CAAC;QACb,IAAI,GAAG,CAAC,CAAC,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsekulowicz/ds-components",
3
- "version": "0.14.0",
3
+ "version": "0.16.1",
4
4
  "description": "Lit web components for the Design System Library (atoms, molecules, organisms, templates, pages).",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {