@rcarls/rc-segmented-button 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +110 -0
- package/README.md +27 -0
- package/dist/custom-elements.json +24 -1
- package/dist/rc-segmented-button-BitI555k.js +126 -0
- package/dist/rc-segmented-button-BitI555k.js.map +1 -0
- package/dist/rc-segmented-button-define.js +1 -1
- package/dist/rc-segmented-button.js +1 -1
- package/dist/types/packages/rc-segmented-button/src/rc-segmented-button.d.ts +18 -2
- package/package.json +4 -1
- package/dist/rc-segmented-button-COV7INIU.js +0 -259
- package/dist/rc-segmented-button-COV7INIU.js.map +0 -1
- package/dist/types/packages/rc-segmented-button/src/rc-segmented-button.test.d.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,115 @@
|
|
|
1
1
|
# @rcarls/rc-segmented-button
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- fef89dc: Move the segmented appearance into the component behind one switch.
|
|
8
|
+
|
|
9
|
+
Turning the native fieldset into a segmented control took 27 `--_rc-*`
|
|
10
|
+
declarations that every theme had to restate, 23 of them byte-identical. Two of
|
|
11
|
+
those blocks were accessibility recipes rather than taste: the visually hidden
|
|
12
|
+
legend that keeps the group's accessible name, and the hidden but focusable
|
|
13
|
+
radio. A theme that got either wrong removed the accessible name or made the
|
|
14
|
+
control unreachable by keyboard.
|
|
15
|
+
|
|
16
|
+
The component now owns the recipe and a theme sets
|
|
17
|
+
`--rc-segmented-button-appearance: segmented`. Four genuine theme choices become
|
|
18
|
+
public properties: `--rc-segmented-button-cursor`,
|
|
19
|
+
`--rc-segmented-button-disabled-cursor`,
|
|
20
|
+
`--rc-segmented-button-vertical-divider`, and
|
|
21
|
+
`--rc-segmented-button-selected-icon-display`.
|
|
22
|
+
|
|
23
|
+
Unset, the fieldset, legend, and radios keep their browser appearance, as
|
|
24
|
+
before. The switch is read with a style container query (Chrome 111, Safari 18,
|
|
25
|
+
Firefox 128); where that is unsupported the recipe does not apply and the
|
|
26
|
+
control falls back to the same native appearance.
|
|
27
|
+
|
|
28
|
+
To migrate a theme, replace its `--_rc-segmented-button-*` block with the single
|
|
29
|
+
`--rc-segmented-button-appearance: segmented` declaration, plus any of the four
|
|
30
|
+
public properties whose value differs from the default.
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- 5c006de: Ship component CSS minified. Package builds now run the CSS in Lit `css` styles
|
|
35
|
+
and light-DOM structural styles through Lightning CSS, removing comments and
|
|
36
|
+
whitespace while keeping source maps that resolve to each template. Rendered
|
|
37
|
+
styles are unchanged.
|
|
38
|
+
|
|
39
|
+
`@rcarls/rc-common` adds `cssText`, an identity tag that marks a plain CSS
|
|
40
|
+
string for minification. `rc-chip`, `rc-disclosure`, and `rc-accordion` now
|
|
41
|
+
depend on `@rcarls/rc-common` for it.
|
|
42
|
+
|
|
43
|
+
- 51f6403: Arrow keys follow the reading direction everywhere. `keyNavigation` now also
|
|
44
|
+
flips the cross axis in RTL, so a vertical menu opens its submenu with
|
|
45
|
+
ArrowLeft, as the APG describes. A horizontal menubar and segmented button
|
|
46
|
+
advance with ArrowLeft in RTL, Alt+ArrowLeft moves items toward the selected
|
|
47
|
+
list of a transfer list in RTL, and the arrow toward the inline start reaches
|
|
48
|
+
the chips of a multiple select or combobox (ArrowRight in RTL).
|
|
49
|
+
|
|
50
|
+
Add `inlineArrowKeys(flow)` for content that runs along the inline axis, such
|
|
51
|
+
as chips or text.
|
|
52
|
+
|
|
53
|
+
- 11680b6: Expose and navigate the orientation a widget actually renders in. An
|
|
54
|
+
`orientation` attribute names a layout: `horizontal` runs along the inline
|
|
55
|
+
axis and `vertical` along the block axis, so both turn over in vertical
|
|
56
|
+
writing modes, the way a native `<input type="range">` does. Toolbar,
|
|
57
|
+
menubar, and adaptive menu now report the rendered orientation as
|
|
58
|
+
`aria-orientation`, and their arrow keys follow it, so a horizontal toolbar
|
|
59
|
+
in vertical text navigates with ArrowDown.
|
|
60
|
+
|
|
61
|
+
`keyNavigation` treats an explicit `navigationAxis` and role defaults as
|
|
62
|
+
layout orientations and converts them the same way; an explicit
|
|
63
|
+
`aria-orientation` attribute is still used as is. Add `renderedOrientation`
|
|
64
|
+
and a `FlowController` that keeps a host's writing mode and direction current
|
|
65
|
+
for rendering.
|
|
66
|
+
|
|
67
|
+
`rc-toolbar` now reflects `orientation` to its host attribute, and its
|
|
68
|
+
vertical layout is keyed off that attribute rather than `aria-orientation`.
|
|
69
|
+
|
|
70
|
+
- fb54f77: Keep the selected segment visible in forced-colors mode.
|
|
71
|
+
|
|
72
|
+
Forced colors replaces the background a theme selects a segment with, which left
|
|
73
|
+
selection legible only through the optional selected-icon slot. The base styles
|
|
74
|
+
now restate the selected segment in `Highlight` and `HighlightText`, matching the
|
|
75
|
+
`rc-chip` treatment, so selection survives in every theme whether or not the icon
|
|
76
|
+
slot is used.
|
|
77
|
+
|
|
78
|
+
- Updated dependencies [e3dfa59]
|
|
79
|
+
- Updated dependencies [50d5610]
|
|
80
|
+
- Updated dependencies [9ee769c]
|
|
81
|
+
- Updated dependencies [1179f24]
|
|
82
|
+
- Updated dependencies [595fe37]
|
|
83
|
+
- Updated dependencies [38cd00c]
|
|
84
|
+
- Updated dependencies [5c006de]
|
|
85
|
+
- Updated dependencies [a6553ff]
|
|
86
|
+
- Updated dependencies [2205478]
|
|
87
|
+
- Updated dependencies [4341311]
|
|
88
|
+
- Updated dependencies [899bb5e]
|
|
89
|
+
- Updated dependencies [25fcfe0]
|
|
90
|
+
- Updated dependencies [51f6403]
|
|
91
|
+
- Updated dependencies [9caca6b]
|
|
92
|
+
- Updated dependencies [b764a3c]
|
|
93
|
+
- Updated dependencies [54d9ead]
|
|
94
|
+
- Updated dependencies [b9175e9]
|
|
95
|
+
- Updated dependencies [c8b762b]
|
|
96
|
+
- Updated dependencies [55e1e7f]
|
|
97
|
+
- Updated dependencies [f1ca82d]
|
|
98
|
+
- Updated dependencies [b87f27b]
|
|
99
|
+
- Updated dependencies [32ebead]
|
|
100
|
+
- Updated dependencies [bfefedd]
|
|
101
|
+
- Updated dependencies [c130173]
|
|
102
|
+
- Updated dependencies [11680b6]
|
|
103
|
+
- Updated dependencies [223d36c]
|
|
104
|
+
- Updated dependencies [7b91a44]
|
|
105
|
+
- Updated dependencies [aa04ead]
|
|
106
|
+
- Updated dependencies [ac65b5b]
|
|
107
|
+
- Updated dependencies [afcfef8]
|
|
108
|
+
- Updated dependencies [11ef1ad]
|
|
109
|
+
- @rcarls/rc-common@0.7.0
|
|
110
|
+
|
|
111
|
+
## 0.6.0
|
|
112
|
+
|
|
3
113
|
## 0.5.0
|
|
4
114
|
|
|
5
115
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -14,3 +14,30 @@ Segmented button group backed by native radio inputs.
|
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
The fieldset, legend, labels, and radios remain in light DOM for forms and no-JavaScript fallback.
|
|
17
|
+
|
|
18
|
+
## Segmented appearance
|
|
19
|
+
|
|
20
|
+
Unstyled, the fieldset, legend, and radios keep their browser appearance. Set
|
|
21
|
+
`--rc-segmented-button-appearance: segmented` to turn on the component's own
|
|
22
|
+
recipe: a flat fieldset, a visually hidden legend, and radios that stay
|
|
23
|
+
focusable and in the accessibility tree while being invisible. The packaged
|
|
24
|
+
themes set it for you.
|
|
25
|
+
|
|
26
|
+
```css
|
|
27
|
+
.my-theme rc-segmented-button {
|
|
28
|
+
--rc-segmented-button-appearance: segmented;
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Browser support
|
|
33
|
+
|
|
34
|
+
That switch is read with a CSS style container query, which has narrower support
|
|
35
|
+
than the rest of this package: Chrome 111, Safari 18, and Firefox 128. Everything
|
|
36
|
+
else here, including the component's behavior, keyboard handling, and form
|
|
37
|
+
participation, works wherever custom elements do.
|
|
38
|
+
|
|
39
|
+
Where style queries are unsupported the recipe simply does not apply and the
|
|
40
|
+
control falls back to the native fieldset and radio appearance, which stays
|
|
41
|
+
fully usable and accessible. Nothing breaks; it looks like plain radio buttons.
|
|
42
|
+
If that fallback is not acceptable for your audience, write the segment layout
|
|
43
|
+
in your own CSS instead of using the switch.
|
|
@@ -49,6 +49,29 @@
|
|
|
49
49
|
"description": "Segmented button group that enhances a direct native `<fieldset>` of radio inputs.",
|
|
50
50
|
"name": "RCSegmentedButton",
|
|
51
51
|
"cssProperties": [
|
|
52
|
+
{
|
|
53
|
+
"description": "Set to `segmented` to turn on the component's segmented recipe: a flat fieldset, a visually hidden legend, and hidden but focusable radios. Unset, the fieldset, legend, and radios keep their browser appearance.",
|
|
54
|
+
"name": "--rc-segmented-button-appearance"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"description": "Segment cursor once the segmented recipe is on.",
|
|
58
|
+
"name": "--rc-segmented-button-cursor",
|
|
59
|
+
"default": "pointer"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"description": "Segment cursor when its radio is disabled, or when the host is `disabled`, once the segmented recipe is on.",
|
|
63
|
+
"name": "--rc-segmented-button-disabled-cursor",
|
|
64
|
+
"default": "not-allowed"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"description": "Border on the inline-start edge of adjacent segments in vertical orientation (defaults to the segment border).",
|
|
68
|
+
"name": "--rc-segmented-button-vertical-divider"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"description": "Display of the selected-icon slot. Set to `none` for a theme that shows selection without a tick.",
|
|
72
|
+
"name": "--rc-segmented-button-selected-icon-display",
|
|
73
|
+
"default": "inline-grid"
|
|
74
|
+
},
|
|
52
75
|
{
|
|
53
76
|
"description": "Gap between segment icon and label content.",
|
|
54
77
|
"name": "--rc-segmented-button-segment-gap",
|
|
@@ -119,7 +142,7 @@
|
|
|
119
142
|
"default": "revert"
|
|
120
143
|
},
|
|
121
144
|
{
|
|
122
|
-
"description": "Segment opacity when its radio is disabled, or when the host is `disabled` (defers to native disabled styling when unset).",
|
|
145
|
+
"description": "Segment opacity when its radio is disabled, or when the host is `disabled` (defers to native disabled styling when unset). Under `forced-colors: active` the selected segment is restated in system colors (`Highlight` / `HighlightText`), so a selected state stays visible even when a theme paints selection with a background the forced palette replaces, and even when the optional selected-icon slot is not used.",
|
|
123
146
|
"name": "--rc-segmented-button-disabled-opacity",
|
|
124
147
|
"default": "revert"
|
|
125
148
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { css as f, LitElement as g, html as p } from "lit";
|
|
2
|
+
import { property as u } from "lit/decorators.js";
|
|
3
|
+
import { resolveFlow as v, arrowKeys as m, renderedOrientation as y, cssText as _ } from "@rcarls/rc-common";
|
|
4
|
+
const k = f`:host{color-scheme:inherit;display:inline-block}:host([hidden]){display:none}`;
|
|
5
|
+
var w = Object.defineProperty, $ = Object.getOwnPropertyDescriptor, c = (h, e, t, i) => {
|
|
6
|
+
for (var s = i > 1 ? void 0 : i ? $(e, t) : e, l = h.length - 1, d; l >= 0; l--)
|
|
7
|
+
(d = h[l]) && (s = (i ? d(e, t, s) : d(s)) || s);
|
|
8
|
+
return i && s && w(e, t, s), s;
|
|
9
|
+
};
|
|
10
|
+
const V = _`@layer rc-base{@container style(--rc-segmented-button-appearance:segmented){rc-segmented-button>fieldset{border:0;border-radius:0;margin:0;padding:0;display:inline-flex;overflow:visible}rc-segmented-button>fieldset>legend{clip:rect(0 0 0 0);white-space:nowrap;border:0;block-size:1px;inline-size:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}rc-segmented-button>fieldset>label{cursor:var(--rc-segmented-button-cursor,pointer);user-select:none;display:inline-flex}rc-segmented-button>fieldset>label:has(input[type=radio]:disabled),rc-segmented-button[disabled]>fieldset>label{cursor:var(--rc-segmented-button-disabled-cursor,not-allowed)}rc-segmented-button[orientation=vertical]>fieldset>label+label{border-inline-start:var(--rc-segmented-button-vertical-divider,var(--rc-segmented-button-border,revert))}rc-segmented-button>fieldset>label>input[type=radio]{opacity:0;pointer-events:none;block-size:1px;inline-size:1px;margin:0;position:absolute}}rc-segmented-button[orientation=vertical]>fieldset{flex-direction:column}rc-segmented-button>fieldset>label{justify-content:center;align-items:center;gap:var(--rc-segmented-button-segment-gap,.5em);min-block-size:var(--rc-segmented-button-segment-min-block-size);padding-block:var(--rc-segmented-button-segment-padding-block,revert);padding-inline:var(--rc-segmented-button-segment-padding-inline,revert);border:var(--rc-segmented-button-border,revert);color:var(--rc-segmented-button-color,revert);background:var(--rc-segmented-button-bg,revert)}rc-segmented-button>fieldset>label:first-of-type{border-start-start-radius:var(--rc-segmented-button-radius,revert);border-end-start-radius:var(--rc-segmented-button-radius,revert)}rc-segmented-button>fieldset>label:last-of-type{border-start-end-radius:var(--rc-segmented-button-radius,revert);border-end-end-radius:var(--rc-segmented-button-radius,revert)}rc-segmented-button>fieldset>label+label{border-inline-start:var(--rc-segmented-button-divider,revert)}rc-segmented-button[orientation=vertical]>fieldset>label+label{border-block-start:var(--rc-segmented-button-divider,revert)}rc-segmented-button[orientation=vertical]>fieldset>label:first-of-type{border-start-start-radius:var(--rc-segmented-button-radius,revert);border-start-end-radius:var(--rc-segmented-button-radius,revert);border-end-start-radius:0}rc-segmented-button[orientation=vertical]>fieldset>label:last-of-type{border-start-end-radius:0;border-end-end-radius:var(--rc-segmented-button-radius,revert);border-end-start-radius:var(--rc-segmented-button-radius,revert)}rc-segmented-button>fieldset>label:has(input[type=radio]:checked){color:var(--rc-segmented-button-selected-color,revert);background:var(--rc-segmented-button-selected-bg,revert)}rc-segmented-button>fieldset>label:has(input[type=radio]:focus-visible){outline:var(--rc-segmented-button-focus-ring,revert);outline-offset:var(--rc-segmented-button-focus-ring-offset,revert)}rc-segmented-button>fieldset>label:has(input[type=radio]:disabled),rc-segmented-button[disabled]>fieldset>label{opacity:var(--rc-segmented-button-disabled-opacity,revert)}rc-segmented-button>fieldset>label>[data-rc-segmented-button-selected-icon]{display:var(--rc-segmented-button-selected-icon-display,inline-grid);inline-size:var(--rc-segmented-button-selected-icon-size,1.25em);visibility:hidden;place-items:center}rc-segmented-button>fieldset>label:has(input[type=radio]:checked)>[data-rc-segmented-button-selected-icon]{visibility:visible}rc-segmented-button>fieldset>label:has([data-rc-segmented-button-selected-icon]):after{content:"";inline-size:var(--rc-segmented-button-selected-icon-size,1.25em);visibility:hidden}@media (forced-colors:active){rc-segmented-button>fieldset>label{color:buttontext;background:buttonface;border-color:buttonborder}rc-segmented-button>fieldset>label:has(input[type=radio]:checked){color:highlighttext;background:highlight;border-color:highlight}}}`;
|
|
11
|
+
var r;
|
|
12
|
+
const o = (r = class extends g {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments), this._value = "", this._defaultValue = "", this._valueInitialized = !1, this._$fieldset = null, this._disabledOwned = !1, this._slotMicrotaskQueued = !1, this.disabled = !1, this.orientation = "horizontal", this._handleChange = (e) => {
|
|
15
|
+
const t = e.target;
|
|
16
|
+
if (!(t instanceof HTMLInputElement) || t.type !== "radio" || !t.checked)
|
|
17
|
+
return;
|
|
18
|
+
const i = this.value;
|
|
19
|
+
this._value = t.value, this._valueInitialized = !0, this.requestUpdate("value", i), this.dispatchEvent(
|
|
20
|
+
new CustomEvent("rc-segmented-button-change", {
|
|
21
|
+
bubbles: !0,
|
|
22
|
+
composed: !0,
|
|
23
|
+
detail: { value: this.value }
|
|
24
|
+
})
|
|
25
|
+
);
|
|
26
|
+
}, this._handleKeyDown = (e) => {
|
|
27
|
+
const t = e.target;
|
|
28
|
+
if (!(t instanceof HTMLInputElement) || t.type !== "radio" || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)
|
|
29
|
+
return;
|
|
30
|
+
const i = v(this), s = m(y(this.orientation, i), i), l = this.orientation === "vertical" ? [s.next] : [s.next, s.openFirst], d = this.orientation === "vertical" ? [s.prev] : [s.prev, s.openLast], n = this._$enabledRadios(), b = n.indexOf(t);
|
|
31
|
+
if (b === -1)
|
|
32
|
+
return;
|
|
33
|
+
let a;
|
|
34
|
+
l.includes(e.key) ? a = n[(b + 1) % n.length] : d.includes(e.key) ? a = n[(b - 1 + n.length) % n.length] : e.key === "Home" ? a = n[0] : e.key === "End" && (a = n[n.length - 1]), a && (e.preventDefault(), a.focus(), a.checked = !0, a.dispatchEvent(new Event("change", { bubbles: !0 })));
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
static _ensureBaseStyles(e) {
|
|
38
|
+
if (r._styledRoots.has(e))
|
|
39
|
+
return;
|
|
40
|
+
r._styledRoots.add(e);
|
|
41
|
+
const t = document.createElement("style");
|
|
42
|
+
t.setAttribute("data-rc-light-dom-base", "rc-segmented-button"), t.textContent = V, e instanceof Document ? e.head.append(t) : e.append(t);
|
|
43
|
+
}
|
|
44
|
+
get value() {
|
|
45
|
+
return this._value || this._defaultValue;
|
|
46
|
+
}
|
|
47
|
+
set value(e) {
|
|
48
|
+
const t = this.value;
|
|
49
|
+
this._value = e ?? "", this._valueInitialized = !0, this._applyValue(!1), this.requestUpdate("value", t);
|
|
50
|
+
}
|
|
51
|
+
get defaultValue() {
|
|
52
|
+
return this._defaultValue;
|
|
53
|
+
}
|
|
54
|
+
set defaultValue(e) {
|
|
55
|
+
const t = this._defaultValue;
|
|
56
|
+
this._defaultValue = e, !this._valueInitialized && !this._value && (this._applyValue(!1), this.requestUpdate("value", t)), this.requestUpdate("defaultValue", t);
|
|
57
|
+
}
|
|
58
|
+
connectedCallback() {
|
|
59
|
+
super.connectedCallback(), r._ensureBaseStyles(this.getRootNode());
|
|
60
|
+
}
|
|
61
|
+
disconnectedCallback() {
|
|
62
|
+
this._$fieldset?.removeEventListener("change", this._handleChange), this._$fieldset?.removeEventListener("keydown", this._handleKeyDown), super.disconnectedCallback();
|
|
63
|
+
}
|
|
64
|
+
firstUpdated() {
|
|
65
|
+
this._syncFieldset();
|
|
66
|
+
}
|
|
67
|
+
updated(e) {
|
|
68
|
+
e.has("disabled") && this._applyDisabled();
|
|
69
|
+
}
|
|
70
|
+
render() {
|
|
71
|
+
return p`<slot @slotchange=${this._handleSlotChange}></slot>`;
|
|
72
|
+
}
|
|
73
|
+
_handleSlotChange() {
|
|
74
|
+
this._slotMicrotaskQueued || (this._slotMicrotaskQueued = !0, queueMicrotask(() => {
|
|
75
|
+
this._slotMicrotaskQueued = !1, this.isConnected && this._syncFieldset();
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
_syncFieldset() {
|
|
79
|
+
const e = this.querySelector(":scope > fieldset");
|
|
80
|
+
if (e === this._$fieldset) {
|
|
81
|
+
this._syncInitialValue(), this._applyValue(!1), this._applyDisabled();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
this._$fieldset?.removeEventListener("change", this._handleChange), this._$fieldset?.removeEventListener("keydown", this._handleKeyDown), this._$fieldset = e, this._disabledOwned = !1, e && (e.addEventListener("change", this._handleChange), e.addEventListener("keydown", this._handleKeyDown)), this._syncInitialValue(), this._applyValue(!1), this._applyDisabled();
|
|
85
|
+
}
|
|
86
|
+
_syncInitialValue() {
|
|
87
|
+
if (this._valueInitialized || this._value)
|
|
88
|
+
return;
|
|
89
|
+
const e = this._$radios.find((t) => t.checked);
|
|
90
|
+
e && (this._value = e.value, this._defaultValue = e.defaultChecked ? e.value : this._defaultValue);
|
|
91
|
+
}
|
|
92
|
+
get _$radios() {
|
|
93
|
+
return this._$fieldset ? Array.from(
|
|
94
|
+
this._$fieldset.querySelectorAll(':scope input[type="radio"]')
|
|
95
|
+
) : [];
|
|
96
|
+
}
|
|
97
|
+
_$enabledRadios() {
|
|
98
|
+
return this._$radios.filter((e) => !e.disabled && !this.disabled);
|
|
99
|
+
}
|
|
100
|
+
_applyValue(e) {
|
|
101
|
+
const t = this._$radios, i = this.value;
|
|
102
|
+
for (const s of t)
|
|
103
|
+
s.checked = s.value === i;
|
|
104
|
+
}
|
|
105
|
+
_applyDisabled() {
|
|
106
|
+
const e = this._$fieldset;
|
|
107
|
+
e && (this.disabled ? (e.disabled || (this._disabledOwned = !0), e.disabled = !0) : this._disabledOwned && (e.disabled = !1, this._disabledOwned = !1));
|
|
108
|
+
}
|
|
109
|
+
}, r.styles = k, r._styledRoots = /* @__PURE__ */ new Set(), r);
|
|
110
|
+
c([
|
|
111
|
+
u({ type: String, reflect: !0 })
|
|
112
|
+
], o.prototype, "value", 1);
|
|
113
|
+
c([
|
|
114
|
+
u({ type: String, attribute: "default-value" })
|
|
115
|
+
], o.prototype, "defaultValue", 1);
|
|
116
|
+
c([
|
|
117
|
+
u({ type: Boolean, reflect: !0 })
|
|
118
|
+
], o.prototype, "disabled", 2);
|
|
119
|
+
c([
|
|
120
|
+
u({ type: String, reflect: !0 })
|
|
121
|
+
], o.prototype, "orientation", 2);
|
|
122
|
+
let E = o;
|
|
123
|
+
export {
|
|
124
|
+
E as R
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=rc-segmented-button-BitI555k.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rc-segmented-button-BitI555k.js","sources":["../src/rc-segmented-button.styles.ts","../src/rc-segmented-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const segmentedButtonStyles = css`\n :host {\n display: inline-block;\n color-scheme: inherit;\n }\n\n :host([hidden]) {\n display: none;\n }\n`;\n\nexport default segmentedButtonStyles;\n","import { LitElement, html } from 'lit';\nimport type { PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport { arrowKeys, cssText, renderedOrientation, resolveFlow } from '@rcarls/rc-common';\n\nimport segmentedButtonStyles from './rc-segmented-button.styles.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-segmented-button': RCSegmentedButton;\n }\n\n interface HTMLElementEventMap {\n 'rc-segmented-button-change': CustomEvent<RCSegmentedButtonChangeDetail>;\n }\n}\n\nconst LIGHT_DOM_CSS = cssText`\n@layer rc-base {\n /*\n * The segmented appearance, behind one switch a theme sets.\n *\n * Everything here is structure rather than paint, and two of the blocks are\n * accessibility recipes rather than taste: the legend stays in the\n * accessibility tree while being visually hidden, and each radio stays\n * focusable and hit-testable through its label while being invisible. A\n * theme that reached for display:none on either would remove the group's\n * accessible name or make the control unreachable by keyboard, so the\n * component owns both rather than restating them per theme.\n *\n * Gating on a style query keeps the documented unthemed contract: with the\n * property unset the fieldset, legend, and radios keep their browser\n * appearance. Where style queries are unsupported the recipe simply does not\n * apply, which lands on that same native appearance.\n */\n @container style(--rc-segmented-button-appearance: segmented) {\n rc-segmented-button > fieldset {\n display: inline-flex;\n margin: 0;\n padding: 0;\n border: 0;\n border-radius: 0;\n overflow: visible;\n }\n\n rc-segmented-button > fieldset > legend {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n }\n\n rc-segmented-button > fieldset > label {\n display: inline-flex;\n cursor: var(--rc-segmented-button-cursor, pointer);\n user-select: none;\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:disabled),\n rc-segmented-button[disabled] > fieldset > label {\n cursor: var(--rc-segmented-button-disabled-cursor, not-allowed);\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset > label + label {\n border-inline-start: var(\n --rc-segmented-button-vertical-divider,\n var(--rc-segmented-button-border, revert)\n );\n }\n\n rc-segmented-button > fieldset > label > input[type='radio'] {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n margin: 0;\n opacity: 0;\n pointer-events: none;\n }\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset {\n flex-direction: column;\n }\n\n rc-segmented-button > fieldset > label {\n align-items: center;\n justify-content: center;\n gap: var(--rc-segmented-button-segment-gap, 0.5em);\n min-block-size: var(--rc-segmented-button-segment-min-block-size);\n padding-block: var(--rc-segmented-button-segment-padding-block, revert);\n padding-inline: var(--rc-segmented-button-segment-padding-inline, revert);\n border: var(--rc-segmented-button-border, revert);\n color: var(--rc-segmented-button-color, revert);\n background: var(--rc-segmented-button-bg, revert);\n }\n\n rc-segmented-button > fieldset > label:first-of-type {\n border-start-start-radius: var(--rc-segmented-button-radius, revert);\n border-end-start-radius: var(--rc-segmented-button-radius, revert);\n }\n\n rc-segmented-button > fieldset > label:last-of-type {\n border-start-end-radius: var(--rc-segmented-button-radius, revert);\n border-end-end-radius: var(--rc-segmented-button-radius, revert);\n }\n\n rc-segmented-button > fieldset > label + label {\n border-inline-start: var(--rc-segmented-button-divider, revert);\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset > label + label {\n border-block-start: var(--rc-segmented-button-divider, revert);\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset > label:first-of-type {\n border-start-start-radius: var(--rc-segmented-button-radius, revert);\n border-start-end-radius: var(--rc-segmented-button-radius, revert);\n border-end-start-radius: 0;\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset > label:last-of-type {\n border-start-end-radius: 0;\n border-end-start-radius: var(--rc-segmented-button-radius, revert);\n border-end-end-radius: var(--rc-segmented-button-radius, revert);\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:checked) {\n color: var(--rc-segmented-button-selected-color, revert);\n background: var(--rc-segmented-button-selected-bg, revert);\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:focus-visible) {\n outline: var(--rc-segmented-button-focus-ring, revert);\n outline-offset: var(--rc-segmented-button-focus-ring-offset, revert);\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:disabled),\n rc-segmented-button[disabled] > fieldset > label {\n opacity: var(--rc-segmented-button-disabled-opacity, revert);\n }\n\n /* Always reserved (never display:none) so a segment's width doesn't\n change between checked/unchecked — only visibility toggles. A fixed\n inline-size keeps the reserved width deterministic regardless of the\n icon's own intrinsic size. */\n rc-segmented-button > fieldset > label > [data-rc-segmented-button-selected-icon] {\n display: var(--rc-segmented-button-selected-icon-display, inline-grid);\n inline-size: var(--rc-segmented-button-selected-icon-size, 1.25em);\n place-items: center;\n visibility: hidden;\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:checked) > [data-rc-segmented-button-selected-icon] {\n visibility: visible;\n }\n\n /* Mirrors the selected-icon slot's reserved width on the opposite side,\n so the label text stays centered instead of leaning toward the\n always-reserved leading icon slot. Logical inline-size + scoping via\n :has() (only labels that opt into the checkmark pattern get a mirror)\n keeps this RTL-correct and backward compatible for consumers not\n using the selected-icon slot at all. */\n rc-segmented-button > fieldset > label:has([data-rc-segmented-button-selected-icon])::after {\n content: '';\n inline-size: var(--rc-segmented-button-selected-icon-size, 1.25em);\n visibility: hidden;\n }\n\n /* Forced colors replaces the palette a theme selects a segment with, so the\n selected state has to be restated in system colors here. Without it the\n only surviving indicator is the optional selected-icon slot, which a theme\n is free to switch off, and a theme that does leaves the control with no\n visible selection at all. Mirrors the rc-chip treatment. */\n @media (forced-colors: active) {\n rc-segmented-button > fieldset > label {\n border-color: ButtonBorder;\n background: ButtonFace;\n color: ButtonText;\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:checked) {\n border-color: Highlight;\n background: Highlight;\n color: HighlightText;\n }\n }\n}\n`;\n\n/** Detail payload for `rc-segmented-button-change`. */\nexport interface RCSegmentedButtonChangeDetail {\n /** Current selected radio value after user interaction. */\n value: string;\n}\n\n/**\n * Segmented button group that enhances a direct native `<fieldset>` of radio inputs.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-segmented-button rc-segmented-button docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/radio/ WAI-ARIA radio group pattern}\n *\n * @slot - A direct `<fieldset>` containing native radio inputs and labels.\n *\n * @fires rc-segmented-button-change - Fired after user interaction changes the selected value.\n *\n * @attr value - Current selected radio value. Host writes are silent.\n * @attr default-value - Initial selected value for uncontrolled usage.\n * @attr disabled - Mirrors disabled state to the native fieldset.\n * @attr orientation - Layout along the inline (`horizontal`) or block (`vertical`) axis. Arrow\n * keys follow the orientation actually rendered, which turns over in vertical writing modes.\n *\n * @cssprop [--rc-segmented-button-appearance] - Set to `segmented` to turn on the component's\n * segmented recipe: a flat fieldset, a visually hidden legend, and hidden but focusable radios.\n * Unset, the fieldset, legend, and radios keep their browser appearance.\n * @cssprop [--rc-segmented-button-cursor=pointer] - Segment cursor once the segmented recipe is on.\n * @cssprop [--rc-segmented-button-disabled-cursor=not-allowed] - Segment cursor when its radio is\n * disabled, or when the host is `disabled`, once the segmented recipe is on.\n * @cssprop [--rc-segmented-button-vertical-divider] - Border on the inline-start edge of adjacent\n * segments in vertical orientation (defaults to the segment border).\n * @cssprop [--rc-segmented-button-selected-icon-display=inline-grid] - Display of the selected-icon\n * slot. Set to `none` for a theme that shows selection without a tick.\n * @cssprop [--rc-segmented-button-segment-gap=0.5em] - Gap between segment icon and label content.\n * @cssprop [--rc-segmented-button-selected-icon-size=1.25em] - Reserved inline-size of the\n * selected-icon slot (and its opposite-side mirror spacer) — constant regardless of checked\n * state, so segment width doesn't change on selection.\n * @cssprop [--rc-segmented-button-segment-min-block-size] - Minimum segment block size (defers\n * to native label layout when unset).\n * @cssprop [--rc-segmented-button-segment-padding-block=revert] - Segment block-axis padding\n * (defers to native label padding when unset).\n * @cssprop [--rc-segmented-button-segment-padding-inline=revert] - Segment inline-axis padding\n * (defers to native label padding when unset).\n * @cssprop [--rc-segmented-button-border=revert] - Segment border (defers to native label border\n * when unset).\n * @cssprop [--rc-segmented-button-color=revert] - Segment text color (defers to native label\n * color when unset).\n * @cssprop [--rc-segmented-button-bg=revert] - Segment background (defers to native label\n * background when unset).\n * @cssprop [--rc-segmented-button-radius=revert] - Rounded corner radius on the first and last\n * segments (defers to native label styling when unset).\n * @cssprop [--rc-segmented-button-divider=revert] - Border between adjacent segments (defers to\n * native label styling when unset).\n * @cssprop [--rc-segmented-button-selected-color=revert] - Segment text color when its radio is\n * checked (defers to native label color when unset).\n * @cssprop [--rc-segmented-button-selected-bg=revert] - Segment background when its radio is\n * checked (defers to native label background when unset).\n * @cssprop [--rc-segmented-button-focus-ring=revert] - Segment outline when its radio is\n * focus-visible (defers to native focus styling when unset).\n * @cssprop [--rc-segmented-button-focus-ring-offset=revert] - Segment outline offset when its\n * radio is focus-visible (defers to native focus styling when unset).\n * @cssprop [--rc-segmented-button-disabled-opacity=revert] - Segment opacity when its radio is\n * disabled, or when the host is `disabled` (defers to native disabled styling when unset).\n *\n * Under `forced-colors: active` the selected segment is restated in system colors\n * (`Highlight` / `HighlightText`), so a selected state stays visible even when a theme\n * paints selection with a background the forced palette replaces, and even when the\n * optional selected-icon slot is not used.\n */\nexport class RCSegmentedButton extends LitElement {\n static override styles = segmentedButtonStyles;\n\n private static readonly _styledRoots = new Set<Document | ShadowRoot>();\n\n private static _ensureBaseStyles(root: Document | ShadowRoot): void {\n if (RCSegmentedButton._styledRoots.has(root)) {\n return;\n }\n\n RCSegmentedButton._styledRoots.add(root);\n\n const style = document.createElement('style');\n\n style.setAttribute('data-rc-light-dom-base', 'rc-segmented-button');\n style.textContent = LIGHT_DOM_CSS;\n\n if (root instanceof Document) {\n root.head.append(style);\n } else {\n root.append(style);\n }\n }\n\n private _value = '';\n private _defaultValue = '';\n private _valueInitialized = false;\n private _$fieldset: HTMLFieldSetElement | null = null;\n private _disabledOwned = false;\n private _slotMicrotaskQueued = false;\n\n /** Current selected radio value. Host writes are silent. */\n @property({ type: String, reflect: true })\n get value(): string {\n return this._value || this._defaultValue;\n }\n\n set value(value: string | undefined) {\n const oldValue = this.value;\n\n this._value = value ?? '';\n this._valueInitialized = true;\n this._applyValue(false);\n this.requestUpdate('value', oldValue);\n }\n\n /** Initial selected value for uncontrolled usage. */\n @property({ type: String, attribute: 'default-value' })\n get defaultValue(): string {\n return this._defaultValue;\n }\n\n set defaultValue(value: string) {\n const oldValue = this._defaultValue;\n\n this._defaultValue = value;\n\n if (!this._valueInitialized && !this._value) {\n this._applyValue(false);\n this.requestUpdate('value', oldValue);\n }\n\n this.requestUpdate('defaultValue', oldValue);\n }\n\n /** Mirror disabled state to the native fieldset. */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /** Keyboard orientation. */\n @property({ type: String, reflect: true })\n orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n override connectedCallback(): void {\n super.connectedCallback();\n RCSegmentedButton._ensureBaseStyles(this.getRootNode() as Document | ShadowRoot);\n }\n\n override disconnectedCallback(): void {\n this._$fieldset?.removeEventListener('change', this._handleChange);\n this._$fieldset?.removeEventListener('keydown', this._handleKeyDown);\n super.disconnectedCallback();\n }\n\n protected override firstUpdated(): void {\n this._syncFieldset();\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n if (changed.has('disabled')) {\n this._applyDisabled();\n }\n }\n\n protected override render() {\n return html`<slot @slotchange=${this._handleSlotChange}></slot>`;\n }\n\n private _handleSlotChange(): void {\n if (this._slotMicrotaskQueued) {\n return;\n }\n\n this._slotMicrotaskQueued = true;\n\n queueMicrotask(() => {\n this._slotMicrotaskQueued = false;\n\n if (this.isConnected) {\n this._syncFieldset();\n }\n });\n }\n\n private _syncFieldset(): void {\n const $nextFieldset = this.querySelector<HTMLFieldSetElement>(':scope > fieldset');\n\n if (!$nextFieldset && import.meta.env.DEV) {\n console.warn(\n '[rc-segmented-button] No direct child <fieldset> found. Place native radio inputs inside a fieldset.',\n this,\n );\n }\n\n if ($nextFieldset === this._$fieldset) {\n this._syncInitialValue();\n this._applyValue(false);\n this._applyDisabled();\n\n return;\n }\n\n this._$fieldset?.removeEventListener('change', this._handleChange);\n this._$fieldset?.removeEventListener('keydown', this._handleKeyDown);\n this._$fieldset = $nextFieldset;\n this._disabledOwned = false;\n\n if ($nextFieldset) {\n $nextFieldset.addEventListener('change', this._handleChange);\n $nextFieldset.addEventListener('keydown', this._handleKeyDown);\n }\n\n this._syncInitialValue();\n this._applyValue(false);\n this._applyDisabled();\n }\n\n private _syncInitialValue(): void {\n if (this._valueInitialized || this._value) {\n return;\n }\n\n const $checked = this._$radios.find(($radio) => $radio.checked);\n\n if ($checked) {\n this._value = $checked.value;\n this._defaultValue = $checked.defaultChecked ? $checked.value : this._defaultValue;\n }\n }\n\n private get _$radios(): HTMLInputElement[] {\n if (!this._$fieldset) {\n return [];\n }\n\n return Array.from(\n this._$fieldset.querySelectorAll<HTMLInputElement>(':scope input[type=\"radio\"]'),\n );\n }\n\n private _$enabledRadios(): HTMLInputElement[] {\n return this._$radios.filter(($radio) => !$radio.disabled && !this.disabled);\n }\n\n private readonly _handleChange = (event: Event): void => {\n const $target = event.target;\n\n if (!($target instanceof HTMLInputElement) || $target.type !== 'radio' || !$target.checked) {\n return;\n }\n\n const oldValue = this.value;\n\n this._value = $target.value;\n this._valueInitialized = true;\n this.requestUpdate('value', oldValue);\n\n this.dispatchEvent(\n new CustomEvent<RCSegmentedButtonChangeDetail>('rc-segmented-button-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n };\n\n private readonly _handleKeyDown = (event: KeyboardEvent): void => {\n const $target = event.target;\n\n if (!($target instanceof HTMLInputElement) || $target.type !== 'radio') {\n return;\n }\n\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n // Keys follow the orientation actually rendered, which turns over in\n // vertical text; horizontal keys flip in RTL. A horizontal layout also\n // accepts the cross-axis keys, as a native radio group does.\n const flow = resolveFlow(this);\n const keys = arrowKeys(renderedOrientation(this.orientation, flow), flow);\n const forwardKeys: string[] =\n this.orientation === 'vertical' ? [keys.next] : [keys.next, keys.openFirst];\n const backwardKeys: string[] =\n this.orientation === 'vertical' ? [keys.prev] : [keys.prev, keys.openLast];\n const $radios = this._$enabledRadios();\n const currentIndex = $radios.indexOf($target);\n\n if (currentIndex === -1) {\n return;\n }\n\n let $next: HTMLInputElement | undefined;\n\n if (forwardKeys.includes(event.key)) {\n $next = $radios[(currentIndex + 1) % $radios.length];\n } else if (backwardKeys.includes(event.key)) {\n $next = $radios[(currentIndex - 1 + $radios.length) % $radios.length];\n } else if (event.key === 'Home') {\n $next = $radios[0];\n } else if (event.key === 'End') {\n $next = $radios[$radios.length - 1];\n }\n\n if (!$next) {\n return;\n }\n\n event.preventDefault();\n $next.focus();\n $next.checked = true;\n $next.dispatchEvent(new Event('change', { bubbles: true }));\n };\n\n private _applyValue(_writeDefault: boolean): void {\n const $radios = this._$radios;\n const value = this.value;\n\n for (const $radio of $radios) {\n $radio.checked = $radio.value === value;\n }\n }\n\n private _applyDisabled(): void {\n const $fieldset = this._$fieldset;\n\n if (!$fieldset) {\n return;\n }\n\n if (this.disabled) {\n if (!$fieldset.disabled) {\n this._disabledOwned = true;\n }\n\n $fieldset.disabled = true;\n } else if (this._disabledOwned) {\n $fieldset.disabled = false;\n this._disabledOwned = false;\n }\n }\n}\n\nexport default RCSegmentedButton;\n"],"names":["segmentedButtonStyles","css","LIGHT_DOM_CSS","cssText","_RCSegmentedButton","_a","LitElement","event","$target","oldValue","flow","resolveFlow","keys","arrowKeys","renderedOrientation","forwardKeys","backwardKeys","$radios","currentIndex","$next","root","style","value","changed","html","$nextFieldset","$checked","$radio","_writeDefault","$fieldset","__decorateClass","property","RCSegmentedButton"],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { R as e } from "./rc-segmented-button-
|
|
1
|
+
import { R as e } from "./rc-segmented-button-BitI555k.js";
|
|
2
2
|
customElements.get("rc-segmented-button") || customElements.define("rc-segmented-button", e);
|
|
3
3
|
//# sourceMappingURL=rc-segmented-button-define.js.map
|
|
@@ -25,8 +25,19 @@ export interface RCSegmentedButtonChangeDetail {
|
|
|
25
25
|
* @attr value - Current selected radio value. Host writes are silent.
|
|
26
26
|
* @attr default-value - Initial selected value for uncontrolled usage.
|
|
27
27
|
* @attr disabled - Mirrors disabled state to the native fieldset.
|
|
28
|
-
* @attr orientation -
|
|
28
|
+
* @attr orientation - Layout along the inline (`horizontal`) or block (`vertical`) axis. Arrow
|
|
29
|
+
* keys follow the orientation actually rendered, which turns over in vertical writing modes.
|
|
29
30
|
*
|
|
31
|
+
* @cssprop [--rc-segmented-button-appearance] - Set to `segmented` to turn on the component's
|
|
32
|
+
* segmented recipe: a flat fieldset, a visually hidden legend, and hidden but focusable radios.
|
|
33
|
+
* Unset, the fieldset, legend, and radios keep their browser appearance.
|
|
34
|
+
* @cssprop [--rc-segmented-button-cursor=pointer] - Segment cursor once the segmented recipe is on.
|
|
35
|
+
* @cssprop [--rc-segmented-button-disabled-cursor=not-allowed] - Segment cursor when its radio is
|
|
36
|
+
* disabled, or when the host is `disabled`, once the segmented recipe is on.
|
|
37
|
+
* @cssprop [--rc-segmented-button-vertical-divider] - Border on the inline-start edge of adjacent
|
|
38
|
+
* segments in vertical orientation (defaults to the segment border).
|
|
39
|
+
* @cssprop [--rc-segmented-button-selected-icon-display=inline-grid] - Display of the selected-icon
|
|
40
|
+
* slot. Set to `none` for a theme that shows selection without a tick.
|
|
30
41
|
* @cssprop [--rc-segmented-button-segment-gap=0.5em] - Gap between segment icon and label content.
|
|
31
42
|
* @cssprop [--rc-segmented-button-selected-icon-size=1.25em] - Reserved inline-size of the
|
|
32
43
|
* selected-icon slot (and its opposite-side mirror spacer) — constant regardless of checked
|
|
@@ -57,6 +68,11 @@ export interface RCSegmentedButtonChangeDetail {
|
|
|
57
68
|
* radio is focus-visible (defers to native focus styling when unset).
|
|
58
69
|
* @cssprop [--rc-segmented-button-disabled-opacity=revert] - Segment opacity when its radio is
|
|
59
70
|
* disabled, or when the host is `disabled` (defers to native disabled styling when unset).
|
|
71
|
+
*
|
|
72
|
+
* Under `forced-colors: active` the selected segment is restated in system colors
|
|
73
|
+
* (`Highlight` / `HighlightText`), so a selected state stays visible even when a theme
|
|
74
|
+
* paints selection with a background the forced palette replaces, and even when the
|
|
75
|
+
* optional selected-icon slot is not used.
|
|
60
76
|
*/
|
|
61
77
|
export declare class RCSegmentedButton extends LitElement {
|
|
62
78
|
static styles: import('lit').CSSResult;
|
|
@@ -82,7 +98,7 @@ export declare class RCSegmentedButton extends LitElement {
|
|
|
82
98
|
disconnectedCallback(): void;
|
|
83
99
|
protected firstUpdated(): void;
|
|
84
100
|
protected updated(changed: PropertyValues<this>): void;
|
|
85
|
-
protected render(): import('lit').TemplateResult<1>;
|
|
101
|
+
protected render(): import('lit-html').TemplateResult<1>;
|
|
86
102
|
private _handleSlotChange;
|
|
87
103
|
private _syncFieldset;
|
|
88
104
|
private _syncInitialValue;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.7.0",
|
|
7
7
|
"description": "Segmented button group backed by native radio inputs.",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -44,6 +44,9 @@
|
|
|
44
44
|
"test:browser:chrome": "vitest --run --project=chromium",
|
|
45
45
|
"test:browser:firefox": "vitest --run --project=firefox"
|
|
46
46
|
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@rcarls/rc-common": "0.7.0"
|
|
49
|
+
},
|
|
47
50
|
"devDependencies": {
|
|
48
51
|
"@custom-elements-manifest/analyzer": "0.11.0",
|
|
49
52
|
"@vitest/browser-playwright": "4.1.5",
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import { css as b, LitElement as v, html as h } from "lit";
|
|
2
|
-
import { property as o } from "lit/decorators.js";
|
|
3
|
-
const g = b`
|
|
4
|
-
:host {
|
|
5
|
-
display: inline-block;
|
|
6
|
-
color-scheme: inherit;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
:host([hidden]) {
|
|
10
|
-
display: none;
|
|
11
|
-
}
|
|
12
|
-
`;
|
|
13
|
-
var f = Object.defineProperty, m = Object.getOwnPropertyDescriptor, c = (u, e, t, i) => {
|
|
14
|
-
for (var s = i > 1 ? void 0 : i ? m(e, t) : e, r = u.length - 1, d; r >= 0; r--)
|
|
15
|
-
(d = u[r]) && (s = (i ? d(e, t, s) : d(s)) || s);
|
|
16
|
-
return i && s && f(e, t, s), s;
|
|
17
|
-
};
|
|
18
|
-
const p = `
|
|
19
|
-
@layer rc-base {
|
|
20
|
-
rc-segmented-button > fieldset {
|
|
21
|
-
display: var(--_rc-segmented-button-fieldset-display, revert);
|
|
22
|
-
margin: var(--_rc-segmented-button-fieldset-margin, revert);
|
|
23
|
-
padding: var(--_rc-segmented-button-fieldset-padding, revert);
|
|
24
|
-
border: var(--_rc-segmented-button-fieldset-border, revert);
|
|
25
|
-
border-radius: var(--_rc-segmented-button-fieldset-radius, revert);
|
|
26
|
-
overflow: var(--_rc-segmented-button-fieldset-overflow, revert);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
rc-segmented-button[orientation='vertical'] > fieldset {
|
|
30
|
-
flex-direction: column;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
rc-segmented-button > fieldset > legend {
|
|
34
|
-
position: var(--_rc-segmented-button-legend-position, revert);
|
|
35
|
-
inline-size: var(--_rc-segmented-button-legend-inline-size, revert);
|
|
36
|
-
block-size: var(--_rc-segmented-button-legend-block-size, revert);
|
|
37
|
-
margin: var(--_rc-segmented-button-legend-margin, revert);
|
|
38
|
-
padding: var(--_rc-segmented-button-legend-padding, revert);
|
|
39
|
-
border: var(--_rc-segmented-button-legend-border, revert);
|
|
40
|
-
overflow: var(--_rc-segmented-button-legend-overflow, revert);
|
|
41
|
-
clip: var(--_rc-segmented-button-legend-clip, revert);
|
|
42
|
-
white-space: var(--_rc-segmented-button-legend-white-space, revert);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
rc-segmented-button > fieldset > label {
|
|
46
|
-
display: var(--_rc-segmented-button-segment-display, revert);
|
|
47
|
-
align-items: center;
|
|
48
|
-
justify-content: center;
|
|
49
|
-
gap: var(--rc-segmented-button-segment-gap, 0.5em);
|
|
50
|
-
min-block-size: var(--rc-segmented-button-segment-min-block-size);
|
|
51
|
-
padding-block: var(--rc-segmented-button-segment-padding-block, revert);
|
|
52
|
-
padding-inline: var(--rc-segmented-button-segment-padding-inline, revert);
|
|
53
|
-
border: var(--rc-segmented-button-border, revert);
|
|
54
|
-
color: var(--rc-segmented-button-color, revert);
|
|
55
|
-
background: var(--rc-segmented-button-bg, revert);
|
|
56
|
-
cursor: var(--_rc-segmented-button-segment-cursor, revert);
|
|
57
|
-
user-select: var(--_rc-segmented-button-segment-user-select, revert);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
rc-segmented-button > fieldset > label:first-of-type {
|
|
61
|
-
border-start-start-radius: var(--rc-segmented-button-radius, revert);
|
|
62
|
-
border-end-start-radius: var(--rc-segmented-button-radius, revert);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
rc-segmented-button > fieldset > label:last-of-type {
|
|
66
|
-
border-start-end-radius: var(--rc-segmented-button-radius, revert);
|
|
67
|
-
border-end-end-radius: var(--rc-segmented-button-radius, revert);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
rc-segmented-button > fieldset > label + label {
|
|
71
|
-
border-inline-start: var(--rc-segmented-button-divider, revert);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
rc-segmented-button[orientation='vertical'] > fieldset > label + label {
|
|
75
|
-
border-inline-start: var(--_rc-segmented-button-vertical-border-inline-start, revert);
|
|
76
|
-
border-block-start: var(--rc-segmented-button-divider, revert);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
rc-segmented-button[orientation='vertical'] > fieldset > label:first-of-type {
|
|
80
|
-
border-start-start-radius: var(--rc-segmented-button-radius, revert);
|
|
81
|
-
border-start-end-radius: var(--rc-segmented-button-radius, revert);
|
|
82
|
-
border-end-start-radius: 0;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
rc-segmented-button[orientation='vertical'] > fieldset > label:last-of-type {
|
|
86
|
-
border-start-end-radius: 0;
|
|
87
|
-
border-end-start-radius: var(--rc-segmented-button-radius, revert);
|
|
88
|
-
border-end-end-radius: var(--rc-segmented-button-radius, revert);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
rc-segmented-button > fieldset > label:has(input[type='radio']:checked) {
|
|
92
|
-
color: var(--rc-segmented-button-selected-color, revert);
|
|
93
|
-
background: var(--rc-segmented-button-selected-bg, revert);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
rc-segmented-button > fieldset > label:has(input[type='radio']:focus-visible) {
|
|
97
|
-
outline: var(--rc-segmented-button-focus-ring, revert);
|
|
98
|
-
outline-offset: var(--rc-segmented-button-focus-ring-offset, revert);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
rc-segmented-button > fieldset > label:has(input[type='radio']:disabled),
|
|
102
|
-
rc-segmented-button[disabled] > fieldset > label {
|
|
103
|
-
opacity: var(--rc-segmented-button-disabled-opacity, revert);
|
|
104
|
-
cursor: var(--_rc-segmented-button-disabled-cursor, revert);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
rc-segmented-button > fieldset > label > input[type='radio'] {
|
|
108
|
-
position: var(--_rc-segmented-button-radio-position, revert);
|
|
109
|
-
inline-size: var(--_rc-segmented-button-radio-inline-size, revert);
|
|
110
|
-
block-size: var(--_rc-segmented-button-radio-block-size, revert);
|
|
111
|
-
margin: var(--_rc-segmented-button-radio-margin, revert);
|
|
112
|
-
opacity: var(--_rc-segmented-button-radio-opacity, revert);
|
|
113
|
-
pointer-events: var(--_rc-segmented-button-radio-pointer-events, revert);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/* Always reserved (never display:none) so a segment's width doesn't
|
|
117
|
-
change between checked/unchecked — only visibility toggles. A fixed
|
|
118
|
-
inline-size keeps the reserved width deterministic regardless of the
|
|
119
|
-
icon's own intrinsic size. */
|
|
120
|
-
rc-segmented-button > fieldset > label > [data-rc-segmented-button-selected-icon] {
|
|
121
|
-
display: var(--_rc-segmented-button-selected-icon-display, inline-grid);
|
|
122
|
-
inline-size: var(--rc-segmented-button-selected-icon-size, 1.25em);
|
|
123
|
-
place-items: center;
|
|
124
|
-
visibility: hidden;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
rc-segmented-button > fieldset > label:has(input[type='radio']:checked) > [data-rc-segmented-button-selected-icon] {
|
|
128
|
-
visibility: visible;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/* Mirrors the selected-icon slot's reserved width on the opposite side,
|
|
132
|
-
so the label text stays centered instead of leaning toward the
|
|
133
|
-
always-reserved leading icon slot. Logical inline-size + scoping via
|
|
134
|
-
:has() (only labels that opt into the checkmark pattern get a mirror)
|
|
135
|
-
keeps this RTL-correct and backward compatible for consumers not
|
|
136
|
-
using the selected-icon slot at all. */
|
|
137
|
-
rc-segmented-button > fieldset > label:has([data-rc-segmented-button-selected-icon])::after {
|
|
138
|
-
content: '';
|
|
139
|
-
inline-size: var(--rc-segmented-button-selected-icon-size, 1.25em);
|
|
140
|
-
visibility: hidden;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
`;
|
|
144
|
-
var n;
|
|
145
|
-
const l = (n = class extends v {
|
|
146
|
-
constructor() {
|
|
147
|
-
super(...arguments), this._value = "", this._defaultValue = "", this._valueInitialized = !1, this._$fieldset = null, this._disabledOwned = !1, this._slotMicrotaskQueued = !1, this.disabled = !1, this.orientation = "horizontal", this._handleChange = (e) => {
|
|
148
|
-
const t = e.target;
|
|
149
|
-
if (!(t instanceof HTMLInputElement) || t.type !== "radio" || !t.checked)
|
|
150
|
-
return;
|
|
151
|
-
const i = this.value;
|
|
152
|
-
this._value = t.value, this._valueInitialized = !0, this.requestUpdate("value", i), this.dispatchEvent(
|
|
153
|
-
new CustomEvent("rc-segmented-button-change", {
|
|
154
|
-
bubbles: !0,
|
|
155
|
-
composed: !0,
|
|
156
|
-
detail: { value: this.value }
|
|
157
|
-
})
|
|
158
|
-
);
|
|
159
|
-
}, this._handleKeyDown = (e) => {
|
|
160
|
-
const t = e.target;
|
|
161
|
-
if (!(t instanceof HTMLInputElement) || t.type !== "radio" || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)
|
|
162
|
-
return;
|
|
163
|
-
const i = this.orientation === "vertical" ? ["ArrowDown"] : ["ArrowRight", "ArrowDown"], s = this.orientation === "vertical" ? ["ArrowUp"] : ["ArrowLeft", "ArrowUp"], r = this._$enabledRadios(), d = r.indexOf(t);
|
|
164
|
-
if (d === -1)
|
|
165
|
-
return;
|
|
166
|
-
let a;
|
|
167
|
-
i.includes(e.key) ? a = r[(d + 1) % r.length] : s.includes(e.key) ? a = r[(d - 1 + r.length) % r.length] : e.key === "Home" ? a = r[0] : e.key === "End" && (a = r[r.length - 1]), a && (e.preventDefault(), a.focus(), a.checked = !0, a.dispatchEvent(new Event("change", { bubbles: !0 })));
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
static _ensureBaseStyles(e) {
|
|
171
|
-
if (n._styledRoots.has(e))
|
|
172
|
-
return;
|
|
173
|
-
n._styledRoots.add(e);
|
|
174
|
-
const t = document.createElement("style");
|
|
175
|
-
t.setAttribute("data-rc-light-dom-base", "rc-segmented-button"), t.textContent = p, e instanceof Document ? e.head.append(t) : e.append(t);
|
|
176
|
-
}
|
|
177
|
-
get value() {
|
|
178
|
-
return this._value || this._defaultValue;
|
|
179
|
-
}
|
|
180
|
-
set value(e) {
|
|
181
|
-
const t = this.value;
|
|
182
|
-
this._value = e ?? "", this._valueInitialized = !0, this._applyValue(!1), this.requestUpdate("value", t);
|
|
183
|
-
}
|
|
184
|
-
get defaultValue() {
|
|
185
|
-
return this._defaultValue;
|
|
186
|
-
}
|
|
187
|
-
set defaultValue(e) {
|
|
188
|
-
const t = this._defaultValue;
|
|
189
|
-
this._defaultValue = e, !this._valueInitialized && !this._value && (this._applyValue(!1), this.requestUpdate("value", t)), this.requestUpdate("defaultValue", t);
|
|
190
|
-
}
|
|
191
|
-
connectedCallback() {
|
|
192
|
-
super.connectedCallback(), n._ensureBaseStyles(this.getRootNode());
|
|
193
|
-
}
|
|
194
|
-
disconnectedCallback() {
|
|
195
|
-
this._$fieldset?.removeEventListener("change", this._handleChange), this._$fieldset?.removeEventListener("keydown", this._handleKeyDown), super.disconnectedCallback();
|
|
196
|
-
}
|
|
197
|
-
firstUpdated() {
|
|
198
|
-
this._syncFieldset();
|
|
199
|
-
}
|
|
200
|
-
updated(e) {
|
|
201
|
-
e.has("disabled") && this._applyDisabled();
|
|
202
|
-
}
|
|
203
|
-
render() {
|
|
204
|
-
return h`<slot @slotchange=${this._handleSlotChange}></slot>`;
|
|
205
|
-
}
|
|
206
|
-
_handleSlotChange() {
|
|
207
|
-
this._slotMicrotaskQueued || (this._slotMicrotaskQueued = !0, queueMicrotask(() => {
|
|
208
|
-
this._slotMicrotaskQueued = !1, this.isConnected && this._syncFieldset();
|
|
209
|
-
}));
|
|
210
|
-
}
|
|
211
|
-
_syncFieldset() {
|
|
212
|
-
const e = this.querySelector(":scope > fieldset");
|
|
213
|
-
if (e === this._$fieldset) {
|
|
214
|
-
this._syncInitialValue(), this._applyValue(!1), this._applyDisabled();
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
this._$fieldset?.removeEventListener("change", this._handleChange), this._$fieldset?.removeEventListener("keydown", this._handleKeyDown), this._$fieldset = e, this._disabledOwned = !1, e && (e.addEventListener("change", this._handleChange), e.addEventListener("keydown", this._handleKeyDown)), this._syncInitialValue(), this._applyValue(!1), this._applyDisabled();
|
|
218
|
-
}
|
|
219
|
-
_syncInitialValue() {
|
|
220
|
-
if (this._valueInitialized || this._value)
|
|
221
|
-
return;
|
|
222
|
-
const e = this._$radios.find((t) => t.checked);
|
|
223
|
-
e && (this._value = e.value, this._defaultValue = e.defaultChecked ? e.value : this._defaultValue);
|
|
224
|
-
}
|
|
225
|
-
get _$radios() {
|
|
226
|
-
return this._$fieldset ? Array.from(
|
|
227
|
-
this._$fieldset.querySelectorAll(':scope input[type="radio"]')
|
|
228
|
-
) : [];
|
|
229
|
-
}
|
|
230
|
-
_$enabledRadios() {
|
|
231
|
-
return this._$radios.filter((e) => !e.disabled && !this.disabled);
|
|
232
|
-
}
|
|
233
|
-
_applyValue(e) {
|
|
234
|
-
const t = this._$radios, i = this.value;
|
|
235
|
-
for (const s of t)
|
|
236
|
-
s.checked = s.value === i;
|
|
237
|
-
}
|
|
238
|
-
_applyDisabled() {
|
|
239
|
-
const e = this._$fieldset;
|
|
240
|
-
e && (this.disabled ? (e.disabled || (this._disabledOwned = !0), e.disabled = !0) : this._disabledOwned && (e.disabled = !1, this._disabledOwned = !1));
|
|
241
|
-
}
|
|
242
|
-
}, n.styles = g, n._styledRoots = /* @__PURE__ */ new Set(), n);
|
|
243
|
-
c([
|
|
244
|
-
o({ type: String, reflect: !0 })
|
|
245
|
-
], l.prototype, "value", 1);
|
|
246
|
-
c([
|
|
247
|
-
o({ type: String, attribute: "default-value" })
|
|
248
|
-
], l.prototype, "defaultValue", 1);
|
|
249
|
-
c([
|
|
250
|
-
o({ type: Boolean, reflect: !0 })
|
|
251
|
-
], l.prototype, "disabled", 2);
|
|
252
|
-
c([
|
|
253
|
-
o({ type: String, reflect: !0 })
|
|
254
|
-
], l.prototype, "orientation", 2);
|
|
255
|
-
let w = l;
|
|
256
|
-
export {
|
|
257
|
-
w as R
|
|
258
|
-
};
|
|
259
|
-
//# sourceMappingURL=rc-segmented-button-COV7INIU.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rc-segmented-button-COV7INIU.js","sources":["../src/rc-segmented-button.styles.ts","../src/rc-segmented-button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const segmentedButtonStyles = css`\n :host {\n display: inline-block;\n color-scheme: inherit;\n }\n\n :host([hidden]) {\n display: none;\n }\n`;\n\nexport default segmentedButtonStyles;\n","import { LitElement, html } from 'lit';\nimport type { PropertyValues } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport segmentedButtonStyles from './rc-segmented-button.styles.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'rc-segmented-button': RCSegmentedButton;\n }\n\n interface HTMLElementEventMap {\n 'rc-segmented-button-change': CustomEvent<RCSegmentedButtonChangeDetail>;\n }\n}\n\nconst LIGHT_DOM_CSS = `\n@layer rc-base {\n rc-segmented-button > fieldset {\n display: var(--_rc-segmented-button-fieldset-display, revert);\n margin: var(--_rc-segmented-button-fieldset-margin, revert);\n padding: var(--_rc-segmented-button-fieldset-padding, revert);\n border: var(--_rc-segmented-button-fieldset-border, revert);\n border-radius: var(--_rc-segmented-button-fieldset-radius, revert);\n overflow: var(--_rc-segmented-button-fieldset-overflow, revert);\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset {\n flex-direction: column;\n }\n\n rc-segmented-button > fieldset > legend {\n position: var(--_rc-segmented-button-legend-position, revert);\n inline-size: var(--_rc-segmented-button-legend-inline-size, revert);\n block-size: var(--_rc-segmented-button-legend-block-size, revert);\n margin: var(--_rc-segmented-button-legend-margin, revert);\n padding: var(--_rc-segmented-button-legend-padding, revert);\n border: var(--_rc-segmented-button-legend-border, revert);\n overflow: var(--_rc-segmented-button-legend-overflow, revert);\n clip: var(--_rc-segmented-button-legend-clip, revert);\n white-space: var(--_rc-segmented-button-legend-white-space, revert);\n }\n\n rc-segmented-button > fieldset > label {\n display: var(--_rc-segmented-button-segment-display, revert);\n align-items: center;\n justify-content: center;\n gap: var(--rc-segmented-button-segment-gap, 0.5em);\n min-block-size: var(--rc-segmented-button-segment-min-block-size);\n padding-block: var(--rc-segmented-button-segment-padding-block, revert);\n padding-inline: var(--rc-segmented-button-segment-padding-inline, revert);\n border: var(--rc-segmented-button-border, revert);\n color: var(--rc-segmented-button-color, revert);\n background: var(--rc-segmented-button-bg, revert);\n cursor: var(--_rc-segmented-button-segment-cursor, revert);\n user-select: var(--_rc-segmented-button-segment-user-select, revert);\n }\n\n rc-segmented-button > fieldset > label:first-of-type {\n border-start-start-radius: var(--rc-segmented-button-radius, revert);\n border-end-start-radius: var(--rc-segmented-button-radius, revert);\n }\n\n rc-segmented-button > fieldset > label:last-of-type {\n border-start-end-radius: var(--rc-segmented-button-radius, revert);\n border-end-end-radius: var(--rc-segmented-button-radius, revert);\n }\n\n rc-segmented-button > fieldset > label + label {\n border-inline-start: var(--rc-segmented-button-divider, revert);\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset > label + label {\n border-inline-start: var(--_rc-segmented-button-vertical-border-inline-start, revert);\n border-block-start: var(--rc-segmented-button-divider, revert);\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset > label:first-of-type {\n border-start-start-radius: var(--rc-segmented-button-radius, revert);\n border-start-end-radius: var(--rc-segmented-button-radius, revert);\n border-end-start-radius: 0;\n }\n\n rc-segmented-button[orientation='vertical'] > fieldset > label:last-of-type {\n border-start-end-radius: 0;\n border-end-start-radius: var(--rc-segmented-button-radius, revert);\n border-end-end-radius: var(--rc-segmented-button-radius, revert);\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:checked) {\n color: var(--rc-segmented-button-selected-color, revert);\n background: var(--rc-segmented-button-selected-bg, revert);\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:focus-visible) {\n outline: var(--rc-segmented-button-focus-ring, revert);\n outline-offset: var(--rc-segmented-button-focus-ring-offset, revert);\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:disabled),\n rc-segmented-button[disabled] > fieldset > label {\n opacity: var(--rc-segmented-button-disabled-opacity, revert);\n cursor: var(--_rc-segmented-button-disabled-cursor, revert);\n }\n\n rc-segmented-button > fieldset > label > input[type='radio'] {\n position: var(--_rc-segmented-button-radio-position, revert);\n inline-size: var(--_rc-segmented-button-radio-inline-size, revert);\n block-size: var(--_rc-segmented-button-radio-block-size, revert);\n margin: var(--_rc-segmented-button-radio-margin, revert);\n opacity: var(--_rc-segmented-button-radio-opacity, revert);\n pointer-events: var(--_rc-segmented-button-radio-pointer-events, revert);\n }\n\n /* Always reserved (never display:none) so a segment's width doesn't\n change between checked/unchecked — only visibility toggles. A fixed\n inline-size keeps the reserved width deterministic regardless of the\n icon's own intrinsic size. */\n rc-segmented-button > fieldset > label > [data-rc-segmented-button-selected-icon] {\n display: var(--_rc-segmented-button-selected-icon-display, inline-grid);\n inline-size: var(--rc-segmented-button-selected-icon-size, 1.25em);\n place-items: center;\n visibility: hidden;\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:checked) > [data-rc-segmented-button-selected-icon] {\n visibility: visible;\n }\n\n /* Mirrors the selected-icon slot's reserved width on the opposite side,\n so the label text stays centered instead of leaning toward the\n always-reserved leading icon slot. Logical inline-size + scoping via\n :has() (only labels that opt into the checkmark pattern get a mirror)\n keeps this RTL-correct and backward compatible for consumers not\n using the selected-icon slot at all. */\n rc-segmented-button > fieldset > label:has([data-rc-segmented-button-selected-icon])::after {\n content: '';\n inline-size: var(--rc-segmented-button-selected-icon-size, 1.25em);\n visibility: hidden;\n }\n}\n`;\n\n/** Detail payload for `rc-segmented-button-change`. */\nexport interface RCSegmentedButtonChangeDetail {\n /** Current selected radio value after user interaction. */\n value: string;\n}\n\n/**\n * Segmented button group that enhances a direct native `<fieldset>` of radio inputs.\n *\n * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-segmented-button rc-segmented-button docs}\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/radio/ WAI-ARIA radio group pattern}\n *\n * @slot - A direct `<fieldset>` containing native radio inputs and labels.\n *\n * @fires rc-segmented-button-change - Fired after user interaction changes the selected value.\n *\n * @attr value - Current selected radio value. Host writes are silent.\n * @attr default-value - Initial selected value for uncontrolled usage.\n * @attr disabled - Mirrors disabled state to the native fieldset.\n * @attr orientation - Keyboard orientation: `horizontal` or `vertical`.\n *\n * @cssprop [--rc-segmented-button-segment-gap=0.5em] - Gap between segment icon and label content.\n * @cssprop [--rc-segmented-button-selected-icon-size=1.25em] - Reserved inline-size of the\n * selected-icon slot (and its opposite-side mirror spacer) — constant regardless of checked\n * state, so segment width doesn't change on selection.\n * @cssprop [--rc-segmented-button-segment-min-block-size] - Minimum segment block size (defers\n * to native label layout when unset).\n * @cssprop [--rc-segmented-button-segment-padding-block=revert] - Segment block-axis padding\n * (defers to native label padding when unset).\n * @cssprop [--rc-segmented-button-segment-padding-inline=revert] - Segment inline-axis padding\n * (defers to native label padding when unset).\n * @cssprop [--rc-segmented-button-border=revert] - Segment border (defers to native label border\n * when unset).\n * @cssprop [--rc-segmented-button-color=revert] - Segment text color (defers to native label\n * color when unset).\n * @cssprop [--rc-segmented-button-bg=revert] - Segment background (defers to native label\n * background when unset).\n * @cssprop [--rc-segmented-button-radius=revert] - Rounded corner radius on the first and last\n * segments (defers to native label styling when unset).\n * @cssprop [--rc-segmented-button-divider=revert] - Border between adjacent segments (defers to\n * native label styling when unset).\n * @cssprop [--rc-segmented-button-selected-color=revert] - Segment text color when its radio is\n * checked (defers to native label color when unset).\n * @cssprop [--rc-segmented-button-selected-bg=revert] - Segment background when its radio is\n * checked (defers to native label background when unset).\n * @cssprop [--rc-segmented-button-focus-ring=revert] - Segment outline when its radio is\n * focus-visible (defers to native focus styling when unset).\n * @cssprop [--rc-segmented-button-focus-ring-offset=revert] - Segment outline offset when its\n * radio is focus-visible (defers to native focus styling when unset).\n * @cssprop [--rc-segmented-button-disabled-opacity=revert] - Segment opacity when its radio is\n * disabled, or when the host is `disabled` (defers to native disabled styling when unset).\n */\nexport class RCSegmentedButton extends LitElement {\n static override styles = segmentedButtonStyles;\n\n private static readonly _styledRoots = new Set<Document | ShadowRoot>();\n\n private static _ensureBaseStyles(root: Document | ShadowRoot): void {\n if (RCSegmentedButton._styledRoots.has(root)) {\n return;\n }\n\n RCSegmentedButton._styledRoots.add(root);\n\n const style = document.createElement('style');\n\n style.setAttribute('data-rc-light-dom-base', 'rc-segmented-button');\n style.textContent = LIGHT_DOM_CSS;\n\n if (root instanceof Document) {\n root.head.append(style);\n } else {\n root.append(style);\n }\n }\n\n private _value = '';\n private _defaultValue = '';\n private _valueInitialized = false;\n private _$fieldset: HTMLFieldSetElement | null = null;\n private _disabledOwned = false;\n private _slotMicrotaskQueued = false;\n\n /** Current selected radio value. Host writes are silent. */\n @property({ type: String, reflect: true })\n get value(): string {\n return this._value || this._defaultValue;\n }\n\n set value(value: string | undefined) {\n const oldValue = this.value;\n\n this._value = value ?? '';\n this._valueInitialized = true;\n this._applyValue(false);\n this.requestUpdate('value', oldValue);\n }\n\n /** Initial selected value for uncontrolled usage. */\n @property({ type: String, attribute: 'default-value' })\n get defaultValue(): string {\n return this._defaultValue;\n }\n\n set defaultValue(value: string) {\n const oldValue = this._defaultValue;\n\n this._defaultValue = value;\n\n if (!this._valueInitialized && !this._value) {\n this._applyValue(false);\n this.requestUpdate('value', oldValue);\n }\n\n this.requestUpdate('defaultValue', oldValue);\n }\n\n /** Mirror disabled state to the native fieldset. */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /** Keyboard orientation. */\n @property({ type: String, reflect: true })\n orientation: 'horizontal' | 'vertical' = 'horizontal';\n\n override connectedCallback(): void {\n super.connectedCallback();\n RCSegmentedButton._ensureBaseStyles(this.getRootNode() as Document | ShadowRoot);\n }\n\n override disconnectedCallback(): void {\n this._$fieldset?.removeEventListener('change', this._handleChange);\n this._$fieldset?.removeEventListener('keydown', this._handleKeyDown);\n super.disconnectedCallback();\n }\n\n protected override firstUpdated(): void {\n this._syncFieldset();\n }\n\n protected override updated(changed: PropertyValues<this>): void {\n if (changed.has('disabled')) {\n this._applyDisabled();\n }\n }\n\n protected override render() {\n return html`<slot @slotchange=${this._handleSlotChange}></slot>`;\n }\n\n private _handleSlotChange(): void {\n if (this._slotMicrotaskQueued) {\n return;\n }\n\n this._slotMicrotaskQueued = true;\n\n queueMicrotask(() => {\n this._slotMicrotaskQueued = false;\n\n if (this.isConnected) {\n this._syncFieldset();\n }\n });\n }\n\n private _syncFieldset(): void {\n const $nextFieldset = this.querySelector<HTMLFieldSetElement>(':scope > fieldset');\n\n if (!$nextFieldset && import.meta.env.DEV) {\n console.warn(\n '[rc-segmented-button] No direct child <fieldset> found. Place native radio inputs inside a fieldset.',\n this,\n );\n }\n\n if ($nextFieldset === this._$fieldset) {\n this._syncInitialValue();\n this._applyValue(false);\n this._applyDisabled();\n\n return;\n }\n\n this._$fieldset?.removeEventListener('change', this._handleChange);\n this._$fieldset?.removeEventListener('keydown', this._handleKeyDown);\n this._$fieldset = $nextFieldset;\n this._disabledOwned = false;\n\n if ($nextFieldset) {\n $nextFieldset.addEventListener('change', this._handleChange);\n $nextFieldset.addEventListener('keydown', this._handleKeyDown);\n }\n\n this._syncInitialValue();\n this._applyValue(false);\n this._applyDisabled();\n }\n\n private _syncInitialValue(): void {\n if (this._valueInitialized || this._value) {\n return;\n }\n\n const $checked = this._$radios.find(($radio) => $radio.checked);\n\n if ($checked) {\n this._value = $checked.value;\n this._defaultValue = $checked.defaultChecked ? $checked.value : this._defaultValue;\n }\n }\n\n private get _$radios(): HTMLInputElement[] {\n if (!this._$fieldset) {\n return [];\n }\n\n return Array.from(\n this._$fieldset.querySelectorAll<HTMLInputElement>(':scope input[type=\"radio\"]'),\n );\n }\n\n private _$enabledRadios(): HTMLInputElement[] {\n return this._$radios.filter(($radio) => !$radio.disabled && !this.disabled);\n }\n\n private readonly _handleChange = (event: Event): void => {\n const $target = event.target;\n\n if (!($target instanceof HTMLInputElement) || $target.type !== 'radio' || !$target.checked) {\n return;\n }\n\n const oldValue = this.value;\n\n this._value = $target.value;\n this._valueInitialized = true;\n this.requestUpdate('value', oldValue);\n\n this.dispatchEvent(\n new CustomEvent<RCSegmentedButtonChangeDetail>('rc-segmented-button-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n };\n\n private readonly _handleKeyDown = (event: KeyboardEvent): void => {\n const $target = event.target;\n\n if (!($target instanceof HTMLInputElement) || $target.type !== 'radio') {\n return;\n }\n\n if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {\n return;\n }\n\n const forwardKeys =\n this.orientation === 'vertical' ? ['ArrowDown'] : ['ArrowRight', 'ArrowDown'];\n const backwardKeys = this.orientation === 'vertical' ? ['ArrowUp'] : ['ArrowLeft', 'ArrowUp'];\n const $radios = this._$enabledRadios();\n const currentIndex = $radios.indexOf($target);\n\n if (currentIndex === -1) {\n return;\n }\n\n let $next: HTMLInputElement | undefined;\n\n if (forwardKeys.includes(event.key)) {\n $next = $radios[(currentIndex + 1) % $radios.length];\n } else if (backwardKeys.includes(event.key)) {\n $next = $radios[(currentIndex - 1 + $radios.length) % $radios.length];\n } else if (event.key === 'Home') {\n $next = $radios[0];\n } else if (event.key === 'End') {\n $next = $radios[$radios.length - 1];\n }\n\n if (!$next) {\n return;\n }\n\n event.preventDefault();\n $next.focus();\n $next.checked = true;\n $next.dispatchEvent(new Event('change', { bubbles: true }));\n };\n\n private _applyValue(_writeDefault: boolean): void {\n const $radios = this._$radios;\n const value = this.value;\n\n for (const $radio of $radios) {\n $radio.checked = $radio.value === value;\n }\n }\n\n private _applyDisabled(): void {\n const $fieldset = this._$fieldset;\n\n if (!$fieldset) {\n return;\n }\n\n if (this.disabled) {\n if (!$fieldset.disabled) {\n this._disabledOwned = true;\n }\n\n $fieldset.disabled = true;\n } else if (this._disabledOwned) {\n $fieldset.disabled = false;\n this._disabledOwned = false;\n }\n }\n}\n\nexport default RCSegmentedButton;\n"],"names":["segmentedButtonStyles","css","LIGHT_DOM_CSS","_RCSegmentedButton","_a","LitElement","event","$target","oldValue","forwardKeys","backwardKeys","$radios","currentIndex","$next","root","style","value","changed","html","$nextFieldset","$checked","$radio","_writeDefault","$fieldset","__decorateClass","property","RCSegmentedButton"],"mappings":"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"}
|
|
File without changes
|