@rcarls/rc-segmented-button 0.4.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/README.md ADDED
@@ -0,0 +1,16 @@
1
+ # @rcarls/rc-segmented-button
2
+
3
+ Segmented button group backed by native radio inputs.
4
+
5
+ ```html
6
+ <rc-segmented-button>
7
+ <fieldset>
8
+ <legend>Text size</legend>
9
+ <label><input type="radio" name="size" value="small" /> Small</label>
10
+ <label><input type="radio" name="size" value="medium" checked /> Medium</label>
11
+ <label><input type="radio" name="size" value="large" /> Large</label>
12
+ </fieldset>
13
+ </rc-segmented-button>
14
+ ```
15
+
16
+ The fieldset, legend, labels, and radios remain in light DOM for forms and no-JavaScript fallback.
@@ -0,0 +1,410 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "readme": "",
4
+ "modules": [
5
+ {
6
+ "kind": "javascript-module",
7
+ "path": "src/define.ts",
8
+ "declarations": [],
9
+ "exports": [
10
+ {
11
+ "kind": "custom-element-definition",
12
+ "name": "rc-segmented-button",
13
+ "declaration": {
14
+ "name": "RCSegmentedButton",
15
+ "module": "/src/rc-segmented-button.js"
16
+ }
17
+ }
18
+ ]
19
+ },
20
+ {
21
+ "kind": "javascript-module",
22
+ "path": "src/index.ts",
23
+ "declarations": [],
24
+ "exports": [
25
+ {
26
+ "kind": "js",
27
+ "name": "RCSegmentedButton",
28
+ "declaration": {
29
+ "name": "default",
30
+ "module": "./rc-segmented-button.js"
31
+ }
32
+ },
33
+ {
34
+ "kind": "js",
35
+ "name": "RCSegmentedButtonChangeDetail",
36
+ "declaration": {
37
+ "name": "RCSegmentedButtonChangeDetail",
38
+ "module": "./rc-segmented-button.js"
39
+ }
40
+ }
41
+ ]
42
+ },
43
+ {
44
+ "kind": "javascript-module",
45
+ "path": "src/rc-segmented-button.ts",
46
+ "declarations": [
47
+ {
48
+ "kind": "class",
49
+ "description": "Segmented button group that enhances a direct native `<fieldset>` of radio inputs.",
50
+ "name": "RCSegmentedButton",
51
+ "cssProperties": [
52
+ {
53
+ "description": "Gap between segment icon and label content (defers to native label layout when unset).",
54
+ "name": "--rc-segmented-button-segment-gap"
55
+ },
56
+ {
57
+ "description": "Minimum segment block size (defers to native label layout when unset).",
58
+ "name": "--rc-segmented-button-segment-min-block-size"
59
+ },
60
+ {
61
+ "description": "Segment block-axis padding (defers to native label padding when unset).",
62
+ "name": "--rc-segmented-button-segment-padding-block",
63
+ "default": "revert"
64
+ },
65
+ {
66
+ "description": "Segment inline-axis padding (defers to native label padding when unset).",
67
+ "name": "--rc-segmented-button-segment-padding-inline",
68
+ "default": "revert"
69
+ },
70
+ {
71
+ "description": "Segment border (defers to native label border when unset).",
72
+ "name": "--rc-segmented-button-border",
73
+ "default": "revert"
74
+ },
75
+ {
76
+ "description": "Segment text color (defers to native label color when unset).",
77
+ "name": "--rc-segmented-button-color",
78
+ "default": "revert"
79
+ },
80
+ {
81
+ "description": "Segment background (defers to native label background when unset).",
82
+ "name": "--rc-segmented-button-bg",
83
+ "default": "revert"
84
+ },
85
+ {
86
+ "description": "Rounded corner radius on the first and last segments (defers to native label styling when unset).",
87
+ "name": "--rc-segmented-button-radius",
88
+ "default": "revert"
89
+ },
90
+ {
91
+ "description": "Border between adjacent segments (defers to native label styling when unset).",
92
+ "name": "--rc-segmented-button-divider",
93
+ "default": "revert"
94
+ },
95
+ {
96
+ "description": "Segment text color when its radio is checked (defers to native label color when unset).",
97
+ "name": "--rc-segmented-button-selected-color",
98
+ "default": "revert"
99
+ },
100
+ {
101
+ "description": "Segment background when its radio is checked (defers to native label background when unset).",
102
+ "name": "--rc-segmented-button-selected-bg",
103
+ "default": "revert"
104
+ },
105
+ {
106
+ "description": "Segment outline when its radio is focus-visible (defers to native focus styling when unset).",
107
+ "name": "--rc-segmented-button-focus-ring",
108
+ "default": "revert"
109
+ },
110
+ {
111
+ "description": "Segment outline offset when its radio is focus-visible (defers to native focus styling when unset).",
112
+ "name": "--rc-segmented-button-focus-ring-offset",
113
+ "default": "revert"
114
+ },
115
+ {
116
+ "description": "Segment opacity when its radio is disabled, or when the host is `disabled` (defers to native disabled styling when unset).",
117
+ "name": "--rc-segmented-button-disabled-opacity",
118
+ "default": "revert"
119
+ }
120
+ ],
121
+ "slots": [
122
+ {
123
+ "description": "A direct `<fieldset>` containing native radio inputs and labels.",
124
+ "name": ""
125
+ }
126
+ ],
127
+ "members": [
128
+ {
129
+ "kind": "field",
130
+ "name": "_styledRoots",
131
+ "privacy": "private",
132
+ "static": true,
133
+ "readonly": true,
134
+ "default": "new Set<Document | ShadowRoot>()"
135
+ },
136
+ {
137
+ "kind": "method",
138
+ "name": "_ensureBaseStyles",
139
+ "privacy": "private",
140
+ "static": true,
141
+ "return": {
142
+ "type": {
143
+ "text": "void"
144
+ }
145
+ },
146
+ "parameters": [
147
+ {
148
+ "name": "root",
149
+ "type": {
150
+ "text": "Document | ShadowRoot"
151
+ }
152
+ }
153
+ ]
154
+ },
155
+ {
156
+ "kind": "field",
157
+ "name": "_value",
158
+ "type": {
159
+ "text": "string"
160
+ },
161
+ "privacy": "private",
162
+ "default": "''"
163
+ },
164
+ {
165
+ "kind": "field",
166
+ "name": "_defaultValue",
167
+ "type": {
168
+ "text": "string"
169
+ },
170
+ "privacy": "private",
171
+ "default": "''"
172
+ },
173
+ {
174
+ "kind": "field",
175
+ "name": "_valueInitialized",
176
+ "type": {
177
+ "text": "boolean"
178
+ },
179
+ "privacy": "private",
180
+ "default": "false"
181
+ },
182
+ {
183
+ "kind": "field",
184
+ "name": "_$fieldset",
185
+ "type": {
186
+ "text": "HTMLFieldSetElement | null"
187
+ },
188
+ "privacy": "private",
189
+ "default": "null"
190
+ },
191
+ {
192
+ "kind": "field",
193
+ "name": "_disabledOwned",
194
+ "type": {
195
+ "text": "boolean"
196
+ },
197
+ "privacy": "private",
198
+ "default": "false"
199
+ },
200
+ {
201
+ "kind": "field",
202
+ "name": "_slotMicrotaskQueued",
203
+ "type": {
204
+ "text": "boolean"
205
+ },
206
+ "privacy": "private",
207
+ "default": "false"
208
+ },
209
+ {
210
+ "kind": "field",
211
+ "name": "value",
212
+ "type": {
213
+ "text": "string"
214
+ },
215
+ "description": "Current selected radio value. Host writes are silent.",
216
+ "attribute": "value",
217
+ "reflects": true
218
+ },
219
+ {
220
+ "kind": "field",
221
+ "name": "defaultValue",
222
+ "type": {
223
+ "text": "string"
224
+ },
225
+ "description": "Initial selected value for uncontrolled usage.",
226
+ "attribute": "default-value"
227
+ },
228
+ {
229
+ "kind": "field",
230
+ "name": "disabled",
231
+ "type": {
232
+ "text": "boolean"
233
+ },
234
+ "default": "false",
235
+ "description": "Mirror disabled state to the native fieldset.",
236
+ "attribute": "disabled",
237
+ "reflects": true
238
+ },
239
+ {
240
+ "kind": "field",
241
+ "name": "orientation",
242
+ "type": {
243
+ "text": "'horizontal' | 'vertical'"
244
+ },
245
+ "default": "'horizontal'",
246
+ "description": "Keyboard orientation.",
247
+ "attribute": "orientation",
248
+ "reflects": true
249
+ },
250
+ {
251
+ "kind": "method",
252
+ "name": "_handleSlotChange",
253
+ "privacy": "private",
254
+ "return": {
255
+ "type": {
256
+ "text": "void"
257
+ }
258
+ }
259
+ },
260
+ {
261
+ "kind": "method",
262
+ "name": "_syncFieldset",
263
+ "privacy": "private",
264
+ "return": {
265
+ "type": {
266
+ "text": "void"
267
+ }
268
+ }
269
+ },
270
+ {
271
+ "kind": "method",
272
+ "name": "_syncInitialValue",
273
+ "privacy": "private",
274
+ "return": {
275
+ "type": {
276
+ "text": "void"
277
+ }
278
+ }
279
+ },
280
+ {
281
+ "kind": "field",
282
+ "name": "_$radios",
283
+ "type": {
284
+ "text": "HTMLInputElement[]"
285
+ },
286
+ "privacy": "private",
287
+ "readonly": true
288
+ },
289
+ {
290
+ "kind": "method",
291
+ "name": "_$enabledRadios",
292
+ "privacy": "private",
293
+ "return": {
294
+ "type": {
295
+ "text": "HTMLInputElement[]"
296
+ }
297
+ }
298
+ },
299
+ {
300
+ "kind": "field",
301
+ "name": "_handleChange",
302
+ "privacy": "private",
303
+ "readonly": true
304
+ },
305
+ {
306
+ "kind": "field",
307
+ "name": "_handleKeyDown",
308
+ "privacy": "private",
309
+ "readonly": true
310
+ },
311
+ {
312
+ "kind": "method",
313
+ "name": "_applyValue",
314
+ "privacy": "private",
315
+ "return": {
316
+ "type": {
317
+ "text": "void"
318
+ }
319
+ },
320
+ "parameters": [
321
+ {
322
+ "name": "_writeDefault",
323
+ "type": {
324
+ "text": "boolean"
325
+ }
326
+ }
327
+ ]
328
+ },
329
+ {
330
+ "kind": "method",
331
+ "name": "_applyDisabled",
332
+ "privacy": "private",
333
+ "return": {
334
+ "type": {
335
+ "text": "void"
336
+ }
337
+ }
338
+ }
339
+ ],
340
+ "events": [
341
+ {
342
+ "description": "Fired after user interaction changes the selected value.",
343
+ "name": "rc-segmented-button-change"
344
+ }
345
+ ],
346
+ "attributes": [
347
+ {
348
+ "description": "Current selected radio value. Host writes are silent.",
349
+ "name": "value",
350
+ "type": {
351
+ "text": "string"
352
+ },
353
+ "fieldName": "value"
354
+ },
355
+ {
356
+ "description": "Initial selected value for uncontrolled usage.",
357
+ "name": "default-value",
358
+ "type": {
359
+ "text": "string"
360
+ },
361
+ "fieldName": "defaultValue"
362
+ },
363
+ {
364
+ "description": "Mirror disabled state to the native fieldset.",
365
+ "name": "disabled",
366
+ "type": {
367
+ "text": "boolean"
368
+ },
369
+ "default": "false",
370
+ "fieldName": "disabled"
371
+ },
372
+ {
373
+ "description": "Keyboard orientation.",
374
+ "name": "orientation",
375
+ "type": {
376
+ "text": "'horizontal' | 'vertical'"
377
+ },
378
+ "default": "'horizontal'",
379
+ "fieldName": "orientation"
380
+ }
381
+ ],
382
+ "superclass": {
383
+ "name": "LitElement",
384
+ "package": "lit"
385
+ },
386
+ "tagName": "rc-segmented-button",
387
+ "customElement": true
388
+ }
389
+ ],
390
+ "exports": [
391
+ {
392
+ "kind": "js",
393
+ "name": "RCSegmentedButton",
394
+ "declaration": {
395
+ "name": "RCSegmentedButton",
396
+ "module": "src/rc-segmented-button.ts"
397
+ }
398
+ },
399
+ {
400
+ "kind": "js",
401
+ "name": "default",
402
+ "declaration": {
403
+ "name": "RCSegmentedButton",
404
+ "module": "src/rc-segmented-button.ts"
405
+ }
406
+ }
407
+ ]
408
+ }
409
+ ]
410
+ }
@@ -0,0 +1,3 @@
1
+ import { R as e } from "./rc-segmented-button-ixogzL_a.js";
2
+ customElements.get("rc-segmented-button") || customElements.define("rc-segmented-button", e);
3
+ //# sourceMappingURL=rc-segmented-button-define.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-segmented-button-define.js","sources":["../src/define.ts"],"sourcesContent":["import RCSegmentedButton from './rc-segmented-button.js';\n\ncustomElements.get('rc-segmented-button') ||\n customElements.define('rc-segmented-button', RCSegmentedButton);\n"],"names":["RCSegmentedButton"],"mappings":";AAEA,eAAe,IAAI,qBAAqB,KACtC,eAAe,OAAO,uBAAuBA,CAAiB;"}
@@ -0,0 +1,241 @@
1
+ import { css as b, LitElement as v, html as g } from "lit";
2
+ import { property as o } from "lit/decorators.js";
3
+ const h = 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, p = Object.getOwnPropertyDescriptor, u = (c, e, t, n) => {
14
+ for (var s = n > 1 ? void 0 : n ? p(e, t) : e, r = c.length - 1, d; r >= 0; r--)
15
+ (d = c[r]) && (s = (n ? d(e, t, s) : d(s)) || s);
16
+ return n && s && f(e, t, s), s;
17
+ };
18
+ const m = `
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);
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
+ rc-segmented-button > fieldset > label > [data-rc-segmented-button-selected-icon] {
117
+ display: none;
118
+ }
119
+
120
+ rc-segmented-button > fieldset > label:has(input[type='radio']:checked) > [data-rc-segmented-button-selected-icon] {
121
+ display: var(--_rc-segmented-button-selected-icon-display, none);
122
+ place-items: center;
123
+ }
124
+ }
125
+ `;
126
+ var i;
127
+ const l = (i = class extends v {
128
+ constructor() {
129
+ 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) => {
130
+ const t = e.target;
131
+ if (!(t instanceof HTMLInputElement) || t.type !== "radio" || !t.checked)
132
+ return;
133
+ const n = this.value;
134
+ this._value = t.value, this._valueInitialized = !0, this.requestUpdate("value", n), this.dispatchEvent(
135
+ new CustomEvent("rc-segmented-button-change", {
136
+ bubbles: !0,
137
+ composed: !0,
138
+ detail: { value: this.value }
139
+ })
140
+ );
141
+ }, this._handleKeyDown = (e) => {
142
+ const t = e.target;
143
+ if (!(t instanceof HTMLInputElement) || t.type !== "radio" || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)
144
+ return;
145
+ const n = this.orientation === "vertical" ? ["ArrowDown"] : ["ArrowRight", "ArrowDown"], s = this.orientation === "vertical" ? ["ArrowUp"] : ["ArrowLeft", "ArrowUp"], r = this._$enabledRadios(), d = r.indexOf(t);
146
+ if (d === -1)
147
+ return;
148
+ let a;
149
+ n.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 })));
150
+ };
151
+ }
152
+ static _ensureBaseStyles(e) {
153
+ if (i._styledRoots.has(e))
154
+ return;
155
+ i._styledRoots.add(e);
156
+ const t = document.createElement("style");
157
+ t.setAttribute("data-rc-light-dom-base", "rc-segmented-button"), t.textContent = m, e instanceof Document ? e.head.append(t) : e.append(t);
158
+ }
159
+ get value() {
160
+ return this._value || this._defaultValue;
161
+ }
162
+ set value(e) {
163
+ const t = this.value;
164
+ this._value = e ?? "", this._valueInitialized = !0, this._applyValue(!1), this.requestUpdate("value", t);
165
+ }
166
+ get defaultValue() {
167
+ return this._defaultValue;
168
+ }
169
+ set defaultValue(e) {
170
+ const t = this._defaultValue;
171
+ this._defaultValue = e, !this._valueInitialized && !this._value && (this._applyValue(!1), this.requestUpdate("value", t)), this.requestUpdate("defaultValue", t);
172
+ }
173
+ connectedCallback() {
174
+ super.connectedCallback(), i._ensureBaseStyles(this.getRootNode());
175
+ }
176
+ disconnectedCallback() {
177
+ this._$fieldset?.removeEventListener("change", this._handleChange), this._$fieldset?.removeEventListener("keydown", this._handleKeyDown), super.disconnectedCallback();
178
+ }
179
+ firstUpdated() {
180
+ this._syncFieldset();
181
+ }
182
+ updated(e) {
183
+ e.has("disabled") && this._applyDisabled();
184
+ }
185
+ render() {
186
+ return g`<slot @slotchange=${this._handleSlotChange}></slot>`;
187
+ }
188
+ _handleSlotChange() {
189
+ this._slotMicrotaskQueued || (this._slotMicrotaskQueued = !0, queueMicrotask(() => {
190
+ this._slotMicrotaskQueued = !1, this.isConnected && this._syncFieldset();
191
+ }));
192
+ }
193
+ _syncFieldset() {
194
+ const e = this.querySelector(":scope > fieldset");
195
+ if (e === this._$fieldset) {
196
+ this._syncInitialValue(), this._applyValue(!1), this._applyDisabled();
197
+ return;
198
+ }
199
+ 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();
200
+ }
201
+ _syncInitialValue() {
202
+ if (this._valueInitialized || this._value)
203
+ return;
204
+ const e = this._$radios.find((t) => t.checked);
205
+ e && (this._value = e.value, this._defaultValue = e.defaultChecked ? e.value : this._defaultValue);
206
+ }
207
+ get _$radios() {
208
+ return this._$fieldset ? Array.from(
209
+ this._$fieldset.querySelectorAll(':scope input[type="radio"]')
210
+ ) : [];
211
+ }
212
+ _$enabledRadios() {
213
+ return this._$radios.filter((e) => !e.disabled && !this.disabled);
214
+ }
215
+ _applyValue(e) {
216
+ const t = this._$radios, n = this.value;
217
+ for (const s of t)
218
+ s.checked = s.value === n;
219
+ }
220
+ _applyDisabled() {
221
+ const e = this._$fieldset;
222
+ e && (this.disabled ? (e.disabled || (this._disabledOwned = !0), e.disabled = !0) : this._disabledOwned && (e.disabled = !1, this._disabledOwned = !1));
223
+ }
224
+ }, i.styles = h, i._styledRoots = /* @__PURE__ */ new Set(), i);
225
+ u([
226
+ o({ type: String, reflect: !0 })
227
+ ], l.prototype, "value", 1);
228
+ u([
229
+ o({ type: String, attribute: "default-value" })
230
+ ], l.prototype, "defaultValue", 1);
231
+ u([
232
+ o({ type: Boolean, reflect: !0 })
233
+ ], l.prototype, "disabled", 2);
234
+ u([
235
+ o({ type: String, reflect: !0 })
236
+ ], l.prototype, "orientation", 2);
237
+ let w = l;
238
+ export {
239
+ w as R
240
+ };
241
+ //# sourceMappingURL=rc-segmented-button-ixogzL_a.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-segmented-button-ixogzL_a.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);\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 rc-segmented-button > fieldset > label > [data-rc-segmented-button-selected-icon] {\n display: none;\n }\n\n rc-segmented-button > fieldset > label:has(input[type='radio']:checked) > [data-rc-segmented-button-selected-icon] {\n display: var(--_rc-segmented-button-selected-icon-display, none);\n place-items: center;\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] - Gap between segment icon and label content\n * (defers to native label layout when unset).\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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"}
@@ -0,0 +1,5 @@
1
+ import { R as o } from "./rc-segmented-button-ixogzL_a.js";
2
+ export {
3
+ o as RCSegmentedButton
4
+ };
5
+ //# sourceMappingURL=rc-segmented-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rc-segmented-button.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,2 @@
1
+ export { default as RCSegmentedButton } from './rc-segmented-button.js';
2
+ export type { RCSegmentedButtonChangeDetail } from './rc-segmented-button.js';
@@ -0,0 +1,94 @@
1
+ import { LitElement, PropertyValues } from 'lit';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'rc-segmented-button': RCSegmentedButton;
5
+ }
6
+ interface HTMLElementEventMap {
7
+ 'rc-segmented-button-change': CustomEvent<RCSegmentedButtonChangeDetail>;
8
+ }
9
+ }
10
+ /** Detail payload for `rc-segmented-button-change`. */
11
+ export interface RCSegmentedButtonChangeDetail {
12
+ /** Current selected radio value after user interaction. */
13
+ value: string;
14
+ }
15
+ /**
16
+ * Segmented button group that enhances a direct native `<fieldset>` of radio inputs.
17
+ *
18
+ * @see {@link https://richardcarls.github.io/rc-webcomponents/components/rc-segmented-button rc-segmented-button docs}
19
+ * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/radio/ WAI-ARIA radio group pattern}
20
+ *
21
+ * @slot - A direct `<fieldset>` containing native radio inputs and labels.
22
+ *
23
+ * @fires rc-segmented-button-change - Fired after user interaction changes the selected value.
24
+ *
25
+ * @attr value - Current selected radio value. Host writes are silent.
26
+ * @attr default-value - Initial selected value for uncontrolled usage.
27
+ * @attr disabled - Mirrors disabled state to the native fieldset.
28
+ * @attr orientation - Keyboard orientation: `horizontal` or `vertical`.
29
+ *
30
+ * @cssprop [--rc-segmented-button-segment-gap] - Gap between segment icon and label content
31
+ * (defers to native label layout when unset).
32
+ * @cssprop [--rc-segmented-button-segment-min-block-size] - Minimum segment block size (defers
33
+ * to native label layout when unset).
34
+ * @cssprop [--rc-segmented-button-segment-padding-block=revert] - Segment block-axis padding
35
+ * (defers to native label padding when unset).
36
+ * @cssprop [--rc-segmented-button-segment-padding-inline=revert] - Segment inline-axis padding
37
+ * (defers to native label padding when unset).
38
+ * @cssprop [--rc-segmented-button-border=revert] - Segment border (defers to native label border
39
+ * when unset).
40
+ * @cssprop [--rc-segmented-button-color=revert] - Segment text color (defers to native label
41
+ * color when unset).
42
+ * @cssprop [--rc-segmented-button-bg=revert] - Segment background (defers to native label
43
+ * background when unset).
44
+ * @cssprop [--rc-segmented-button-radius=revert] - Rounded corner radius on the first and last
45
+ * segments (defers to native label styling when unset).
46
+ * @cssprop [--rc-segmented-button-divider=revert] - Border between adjacent segments (defers to
47
+ * native label styling when unset).
48
+ * @cssprop [--rc-segmented-button-selected-color=revert] - Segment text color when its radio is
49
+ * checked (defers to native label color when unset).
50
+ * @cssprop [--rc-segmented-button-selected-bg=revert] - Segment background when its radio is
51
+ * checked (defers to native label background when unset).
52
+ * @cssprop [--rc-segmented-button-focus-ring=revert] - Segment outline when its radio is
53
+ * focus-visible (defers to native focus styling when unset).
54
+ * @cssprop [--rc-segmented-button-focus-ring-offset=revert] - Segment outline offset when its
55
+ * radio is focus-visible (defers to native focus styling when unset).
56
+ * @cssprop [--rc-segmented-button-disabled-opacity=revert] - Segment opacity when its radio is
57
+ * disabled, or when the host is `disabled` (defers to native disabled styling when unset).
58
+ */
59
+ export declare class RCSegmentedButton extends LitElement {
60
+ static styles: import('lit').CSSResult;
61
+ private static readonly _styledRoots;
62
+ private static _ensureBaseStyles;
63
+ private _value;
64
+ private _defaultValue;
65
+ private _valueInitialized;
66
+ private _$fieldset;
67
+ private _disabledOwned;
68
+ private _slotMicrotaskQueued;
69
+ /** Current selected radio value. Host writes are silent. */
70
+ get value(): string;
71
+ set value(value: string | undefined);
72
+ /** Initial selected value for uncontrolled usage. */
73
+ get defaultValue(): string;
74
+ set defaultValue(value: string);
75
+ /** Mirror disabled state to the native fieldset. */
76
+ disabled: boolean;
77
+ /** Keyboard orientation. */
78
+ orientation: 'horizontal' | 'vertical';
79
+ connectedCallback(): void;
80
+ disconnectedCallback(): void;
81
+ protected firstUpdated(): void;
82
+ protected updated(changed: PropertyValues<this>): void;
83
+ protected render(): import('lit').TemplateResult<1>;
84
+ private _handleSlotChange;
85
+ private _syncFieldset;
86
+ private _syncInitialValue;
87
+ private get _$radios();
88
+ private _$enabledRadios;
89
+ private readonly _handleChange;
90
+ private readonly _handleKeyDown;
91
+ private _applyValue;
92
+ private _applyDisabled;
93
+ }
94
+ export default RCSegmentedButton;
@@ -0,0 +1,2 @@
1
+ export declare const segmentedButtonStyles: import('lit').CSSResult;
2
+ export default segmentedButtonStyles;
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@rcarls/rc-segmented-button",
3
+ "publishConfig": {
4
+ "access": "public"
5
+ },
6
+ "version": "0.4.0",
7
+ "description": "Segmented button group backed by native radio inputs.",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/richardcarls/rc-webcomponents.git",
11
+ "directory": "packages/rc-segmented-button"
12
+ },
13
+ "homepage": "https://richardcarls.github.io/rc-webcomponents/components/rc-segmented-button",
14
+ "license": "MIT",
15
+ "type": "module",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "module": "./dist/rc-segmented-button.js",
20
+ "exports": {
21
+ ".": {
22
+ "import": {
23
+ "types": "./dist/types/packages/rc-segmented-button/src/index.d.ts",
24
+ "default": "./dist/rc-segmented-button.js"
25
+ }
26
+ },
27
+ "./define": {
28
+ "import": {
29
+ "types": "./dist/types/packages/rc-segmented-button/src/define.d.ts",
30
+ "default": "./dist/rc-segmented-button-define.js"
31
+ }
32
+ }
33
+ },
34
+ "types": "./dist/types/packages/rc-segmented-button/src/index.d.ts",
35
+ "sideEffects": [
36
+ "./dist/rc-segmented-button-define.js"
37
+ ],
38
+ "customElements": "dist/custom-elements.json",
39
+ "scripts": {
40
+ "build": "tsc && vite build && cem analyze",
41
+ "cem:analyze": "cem analyze",
42
+ "preview": "vite preview",
43
+ "test:browser": "vitest --run",
44
+ "test:browser:chrome": "vitest --run --project=chromium",
45
+ "test:browser:firefox": "vitest --run --project=firefox"
46
+ },
47
+ "devDependencies": {
48
+ "@custom-elements-manifest/analyzer": "0.11.0",
49
+ "@vitest/browser-playwright": "4.1.5",
50
+ "lit": "^3.0.0",
51
+ "playwright": "^1.56.0",
52
+ "rollup": "^4.60.2",
53
+ "typescript": "~5.9.3",
54
+ "vite": "^7.1.7",
55
+ "vite-plugin-dts": "^4.5.4",
56
+ "vitest": "^4.0.6",
57
+ "vitest-browser-lit": "^1.0.1"
58
+ },
59
+ "peerDependencies": {
60
+ "lit": "^3.0.0"
61
+ }
62
+ }