@nysds/nys-radiobutton 1.13.1 → 1.15.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/dist/index.d.ts +2 -0
- package/dist/nys-radiobutton.d.ts +99 -0
- package/dist/nys-radiobutton.js +229 -110
- package/dist/nys-radiobutton.js.map +1 -1
- package/dist/nys-radiogroup.d.ts +108 -0
- package/package.json +4 -4
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
import "./nys-radiogroup";
|
|
3
|
+
/**
|
|
4
|
+
* A radio button for single selection within a `nys-radiogroup`. Only one radio with the same `name` can be selected.
|
|
5
|
+
*
|
|
6
|
+
* Use within `nys-radiogroup` for 2-6 mutually exclusive options. For 7+ options, use `nys-select`.
|
|
7
|
+
* For multiple selections, use `nys-checkbox`.
|
|
8
|
+
*
|
|
9
|
+
* @summary Radio button for single selection from mutually exclusive options.
|
|
10
|
+
* @element nys-radiobutton
|
|
11
|
+
*
|
|
12
|
+
* @slot description - Custom HTML description content.
|
|
13
|
+
*
|
|
14
|
+
* @fires nys-change - Fired when selection changes. Detail: `{id, checked, name, value}`.
|
|
15
|
+
* @fires nys-focus - Fired when radio gains focus.
|
|
16
|
+
* @fires nys-blur - Fired when radio loses focus.
|
|
17
|
+
* @fires nys-other-input - Fired when "other" text input value changes. Detail: `{id, name, value}`.
|
|
18
|
+
*
|
|
19
|
+
* @example Radio group
|
|
20
|
+
* ```html
|
|
21
|
+
* <nys-radiogroup label="Select borough" required>
|
|
22
|
+
* <nys-radiobutton name="borough" value="bronx" label="The Bronx"></nys-radiobutton>
|
|
23
|
+
* <nys-radiobutton name="borough" value="brooklyn" label="Brooklyn"></nys-radiobutton>
|
|
24
|
+
* </nys-radiogroup>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class NysRadiobutton extends LitElement {
|
|
28
|
+
static styles: import("lit").CSSResult;
|
|
29
|
+
static shadowRootOptions: {
|
|
30
|
+
delegatesFocus: boolean;
|
|
31
|
+
clonable?: boolean;
|
|
32
|
+
customElementRegistry?: CustomElementRegistry;
|
|
33
|
+
mode: ShadowRootMode;
|
|
34
|
+
serializable?: boolean;
|
|
35
|
+
slotAssignment?: SlotAssignmentMode;
|
|
36
|
+
};
|
|
37
|
+
/** Whether this radio is selected. Only one per group can be checked. */
|
|
38
|
+
checked: boolean;
|
|
39
|
+
/** Prevents interaction. */
|
|
40
|
+
disabled: boolean;
|
|
41
|
+
/** Marks group as required. Set on radiogroup, not individual radios. */
|
|
42
|
+
required: boolean;
|
|
43
|
+
/** Visible label text. Required for accessibility. */
|
|
44
|
+
label: string;
|
|
45
|
+
/** Helper text below label. Use slot for custom HTML. */
|
|
46
|
+
description: string;
|
|
47
|
+
/** Unique identifier. Auto-generated if not provided. */
|
|
48
|
+
id: string;
|
|
49
|
+
/** Group name. Radios with same name are mutually exclusive. */
|
|
50
|
+
name: string;
|
|
51
|
+
/** Value submitted when this radio is selected. */
|
|
52
|
+
value: string;
|
|
53
|
+
/** Adjusts colors for dark backgrounds. */
|
|
54
|
+
inverted: boolean;
|
|
55
|
+
/** Form `id` to associate with. */
|
|
56
|
+
form: string | null;
|
|
57
|
+
/**
|
|
58
|
+
* Radio size: `sm` (24px) or `md` (32px, default).
|
|
59
|
+
* @default "md"
|
|
60
|
+
*/
|
|
61
|
+
size: "sm" | "md";
|
|
62
|
+
/** Renders as tile with larger clickable area. */
|
|
63
|
+
tile: boolean;
|
|
64
|
+
other: boolean;
|
|
65
|
+
showOtherError: boolean;
|
|
66
|
+
private isMobile;
|
|
67
|
+
private _hasUserInteracted;
|
|
68
|
+
static buttonGroup: Record<string, NysRadiobutton>;
|
|
69
|
+
/**
|
|
70
|
+
* Lifecycle methods
|
|
71
|
+
* --------------------------------------------------------------------------
|
|
72
|
+
*/
|
|
73
|
+
connectedCallback(): void;
|
|
74
|
+
disconnectedCallback(): void;
|
|
75
|
+
updated(changedProperties: Map<string | number | symbol, unknown>): void;
|
|
76
|
+
/**
|
|
77
|
+
* Functions
|
|
78
|
+
* --------------------------------------------------------------------------
|
|
79
|
+
*/
|
|
80
|
+
getInputElement(): Promise<HTMLInputElement | null>;
|
|
81
|
+
formResetUpdate(): void;
|
|
82
|
+
private _handleResize;
|
|
83
|
+
private _clearOtherState;
|
|
84
|
+
/**
|
|
85
|
+
* Event Handlers
|
|
86
|
+
* --------------------------------------------------------------------------
|
|
87
|
+
*/
|
|
88
|
+
private _emitChangeEvent;
|
|
89
|
+
private _emitOtherInputEvent;
|
|
90
|
+
private _handleChange;
|
|
91
|
+
private _handleFocus;
|
|
92
|
+
private _handleBlur;
|
|
93
|
+
private _callInputHandling;
|
|
94
|
+
private _handleTextInput;
|
|
95
|
+
private _handleTextInputBlur;
|
|
96
|
+
private _validateOtherAndEmitError;
|
|
97
|
+
private _handleOtherKeydown;
|
|
98
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
99
|
+
}
|
package/dist/nys-radiobutton.js
CHANGED
|
@@ -1,21 +1,31 @@
|
|
|
1
|
-
import { LitElement as
|
|
1
|
+
import { LitElement as f, unsafeCSS as k, html as v } from "lit";
|
|
2
2
|
import { property as r, state as m } from "lit/decorators.js";
|
|
3
|
-
import { ifDefined as
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
import { ifDefined as _ } from "lit/directives/if-defined.js";
|
|
4
|
+
/*!
|
|
5
|
+
* █▄ █ █ █ █▀▀▀█ █▀▀▄ █▀▀▀█
|
|
6
|
+
* █ █ █ █▄▄▄█ ▀▀▀▄▄ █ █ ▀▀▀▄▄
|
|
7
|
+
* █ ▀█ █ █▄▄▄█ █▄▄▀ █▄▄▄█
|
|
8
|
+
*
|
|
9
|
+
* Radiobutton Component
|
|
10
|
+
* Part of the New York State Design System
|
|
11
|
+
* Repository: https://github.com/its-hcd/nysds
|
|
12
|
+
* License: MIT
|
|
13
|
+
*/
|
|
14
|
+
const w = `:host{--_nys-radiobutton-size: var(--nys-size-400, 32px);--_nys-radiobutton-border-radius: var(--nys-radius-md, 4px);--_nys-radiobutton-border-width: var(--nys-border-width-md, 2px);--_nys-radiobutton-outline-color: var(--nys-color-focus, #004dd1);--_nys-radiobutton-outline-width: var(--nys-border-width-md, 2px);--_nys-radiobutton-outline-offset: var(--nys-space-2px, 2px);--_nys-radiobutton-gap: var(--nys-space-150, 12px);--_nys-radiogroup-gap: var(--nys-space-200, 16px);--_nys-radiobutton-font-family: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-radiobutton-font-size: var(--nys-font-size-ui-md, 16px);--_nys-radiobutton-font-weight--label: var(--nys-font-weight-regular, 400);--_nys-radiobutton-line-height: var(--nys-font-lineheight-ui-md, 24px);--_nys-radiobutton-color: var( --nys-color-text, var(--nys-color-neutral-900, #1b1b1b) );--_nys-radiobutton-background-color: var(--nys-color-ink-reverse, #ffffff);--_nys-radiobutton-border-color: var(--nys-color-neutral-600, #62666a);--_nys-radiobutton-background-color--hover: var( --nys-color-neutral-50, #ededed );--_nys-radiobutton-border-color--hover: var(--nys-color-ink, #1b1b1b);--_nys-radiobutton-background-color--active: var( --nys-color-neutral-100, #d0d0ce );--_nys-radiobutton-border-color--active: var(--nys-color-ink, #1b1b1b);--_nys-radiobutton-background-color--checked: var(--nys-color-theme, #154973);--_nys-radiobutton-background-color--disabled: var( --nys-color-ink-reverse, #f0f0f0 );--_nys-radiobutton-color--disabled: var(--nys-color-text-disabled, #bec0c1);--_nys-radiobutton-border-color--disabled: var( --nys-color-neutral-100, #d0d0ce );--_nys-radiobutton-background-color--checked--disabled: var( --nys-color-neutral-100, #d0d0ce );--_nys-radiobutton-border-color--checked--disabled: var( --nys-color-neutral-100, #d0d0ce )}:host([size=sm]){--_nys-radiobutton-size: var(--nys-size-300, 24px);--_nys-radiobutton-border-radius: var(--nys-radius-sm, 2px);--_nys-radiogroup-gap: var(--nys-space-100, 8px);--_nys-radiobutton-gap: var(--nys-space-100, 8px)}:host([size=md]){--_nys-radiobutton-size: var(--nys-size-400, 32px);--_nys-radiobutton-border-radius: var(--nys-radius-md, 4px);--_nys-radiogroup-gap: var(--nys-space-200, 16px);--_nys-radiobutton-gap: var(--nys-space-150, 12px)}:host([tile]){--_nys-radiobutton-font-weight--label: var(--nys-font-weight-semibold, 600);--_nys-radiobutton-border-width--tile: var(--nys-border-width-sm, 1px);--_nys-radiobutton-border-radius--tile: var(--nys-radius-md, 4px);--_nys-radiobutton-border-color--tile: var(--nys-color-neutral-100, #d0d0ce);--_nys-radiobutton-background-color--tile: var(--nys-color-ink-reverse, #ffffff);--_nys-radiobutton-padding--x--tile: var(--nys-space-250, 20px);--_nys-radiobutton-padding--y--tile: var(--nys-space-200, 16px);--_nys-radiobutton-border-color--tile--hover: var( --nys-color-neutral-700, #4a4d4f );--_nys-radiobutton-background-color--tile--hover: var( --nys-color-ink-reverse, #ffffff );--_nys-radiobutton-border-color--tile--active: var( --nys-color-neutral-900, #1b1b1b );--_nys-radiobutton-background-color--tile--active: var( --nys-color-ink-reverse, #ffffff );--_nys-radiobutton-border-color--tile--checked: var( --nys-color-theme-mid, #457aa5 );--_nys-radiobutton-background-color--tile--checked: var( --nys-color-theme-faint, #f7fafd );--_nys-radiobutton-border-color--tile--disabled: var( --nys-color-ink-reverse, #f0f0f0 );--_nys-radiobutton-background-color--tile--disabled: var( --nys-color-neutral-100, #d0d0ce )}:host([tile][size=sm]){--_nys-radiobutton-padding--x--tile: var(--nys-space-200, 16px);--_nys-radiobutton-padding--y--tile: var(--nys-space-150, 12px)}:host([tile][showError]){--_nys-radiobutton-border-color--tile: var(--nys-color-danger, #b52c2c);--_nys-radiobutton-border-color--tile--hover: var( --nys-color-danger, #b52c2c );--_nys-radiobutton-border-color--tile--active: var( --nys-color-danger, #b52c2c );--_nys-radiobutton-border-color--tile--checked: var( --nys-color-danger, #b52c2c )}.nys-radiogroup{display:flex;flex-direction:column;gap:var(--nys-space-200, 16px);font-family:var(--_nys-radiobutton-font-family);font-size:var(--_nys-radiobutton-font-size);line-height:var(--_nys-radiobutton-line-height)}.nys-radiogroup__content{gap:var(--_nys-radiogroup-gap);display:flex;flex-direction:column}.nys-radiobutton{display:flex;flex-direction:column;font-family:var(--_nys-radiobutton-font-family);font-size:var(--_nys-radiobutton-font-size);line-height:var(--_nys-radiobutton-line-height);border-radius:var(--_nys-radiobutton-border-radius--tile);border:var(--_nys-radiobutton-border-width--tile) solid var(--_nys-radiobutton-border-color--tile);background-color:var(--_nys-radiobutton-background-color--tile);padding:var(--_nys-radiobutton-padding--y--tile) var(--_nys-radiobutton-padding--x--tile)}.nys-radiobutton__radio{appearance:none;width:var(--_nys-radiobutton-size);height:var(--_nys-radiobutton-size);min-width:var(--_nys-radiobutton-size);min-height:var(--_nys-radiobutton-size);max-width:var(--_nys-radiobutton-size);max-height:var(--_nys-radiobutton-size);border:solid var(--_nys-radiobutton-border-width) var(--_nys-radiobutton-border-color);background-color:var(--_nys-radiobutton-background-color);border-radius:100%;background-repeat:no-repeat;background-position:center;background-size:contain;outline-offset:var(--_nys-radiobutton-outline-offset);outline:none;margin:0 0 auto;box-sizing:border-box}.nys-radiobutton:hover,.nys-radiobutton:hover *{cursor:pointer}input:not(:disabled):checked+.nys-radiobutton .nys-radiobutton__radio{background-image:url('data:image/svg+xml;utf8,<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="11" cy="11" r="11" stroke="white" stroke-width="6"/></svg>');background-color:var(--_nys-radiobutton-background-color--checked)}:host([tile]) .nys-radiobutton:has(input:not(:disabled):checked)+.nys-radiobutton .nys-radiobutton__radio{border-color:var(--_nys-radiobutton-border-color--tile--checked);background-color:var(--_nys-radiobutton-background-color--tile--checked)}:host([tile]) .nys-radiobutton:has(input:not(:disabled):checked:hover)+.nys-radiobutton .nys-radiobutton__radio{cursor:default}input:disabled:checked+.nys-radiobutton .nys-radiobutton__radio{background-image:url('data:image/svg+xml;utf8,<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="11" cy="11" r="11" stroke="white" stroke-width="6"/></svg>');border-color:var(--_nys-radiobutton-border-color--checked--disabled);background-color:var(--_nys-radiobutton-background-color--checked--disabled)}:host([tile]) .nys-radiobutton:has(input:disabled:checked)+.nys-radiobutton .nys-radiobutton__radio{border-color:var(--_nys-radiobutton-background-color--tile--disabled);background-color:var(--_nys-radiobutton-border-color--tile--disabled)}input:disabled+.nys-radiobutton,input:disabled+.nys-radiobutton *{cursor:not-allowed}input:disabled+.nys-radiobutton .nys-radiobutton__radio{background-color:var(--_nys-radiobutton-background-color--disabled);border-color:var(--_nys-radiobutton-border-color--disabled);cursor:not-allowed}:host([tile]) .nys-radiobutton:has(input:disabled)+.nys-radiobutton .nys-radiobutton__radio{background-color:var(--_nys-radiobutton-background-color--disabled);border-color:var(--_nys-radiobutton-border-color--disabled);cursor:not-allowed}input:hover:not(:disabled):not(:checked)+.nys-radiobutton .nys-radiobutton__radio,input:not(:disabled):not(:checked)+.nys-radiobutton:hover .nys-radiobutton__radio{border-color:var(--_nys-radiobutton-border-color--hover);background-color:var(--_nys-radiobutton-background-color--hover)}:host([tile]) input:not(:disabled):not(:checked)+.nys-radiobutton:hover{border-color:var(--_nys-radiobutton-border-color--tile--hover);background-color:var(--_nys-radiobutton-background-color--tile--hover);outline:solid var(--_nys-radiobutton-border-width--tile) var(--_nys-radiobutton-border-color--tile--hover)}input:active:not(:disabled):not(:checked)+.nys-radiobutton .nys-radiobutton__radio,input:not(:disabled):not(:checked)+.nys-radiobutton:active .nys-radiobutton__radio{border-color:var(--_nys-radiobutton-border-color--active);background-color:var(--_nys-radiobutton-background-color--active)}:host([tile]) input:not(:disabled):not(:checked)+.nys-radiobutton:active{border-color:var(--_nys-radiobutton-border-color--tile--active);background-color:var(--_nys-radiobutton-background-color--tile--active);outline:solid var(--_nys-radiobutton-border-width--tile) var(--_nys-radiobutton-border-color--tile--active)}:host(:focus-visible){outline:none}:host(:focus-visible) .nys-radiobutton__radio{outline:solid var(--_nys-radiobutton-outline-width) var(--_nys-radiobutton-outline-color)}input:focus-visible+.nys-radiobutton .nys-radiobutton__radio,.nys-radiobutton:has(:focus-visible) .nys-radiobutton__radio{outline:solid var(--_nys-radiobutton-outline-width) var(--_nys-radiobutton-outline-color);outline-offset:var(--_nys-radiobutton-outline-offset)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.nys-radiobutton__main-container{display:flex;align-items:center}.nys-radiobutton__other-container{display:flex;padding-inline-start:calc(var(--_nys-radiobutton-size) + var(--_nys-radiobutton-gap))}.nys-radiobutton__main-container>nys-label{--_nys-label-font-weight: var(--_nys-radiobutton-font-weight--label);display:flex;padding-inline-start:var(--_nys-radiobutton-gap)}:host([tile]) .nys-radiobutton__main-container>nys-label{--_nys-description-font-style: normal}input:disabled+.nys-radiobutton .nys-radiobutton__main-container>nys-label,input:disabled+.nys-radiobutton .nys-radiobutton__main-container>nys-label *{cursor:not-allowed;--_nys-label-cursor: not-allowed;--_nys-label-color: var(--_nys-radiobutton-color--disabled);--_nys-description-color: var(--_nys-radiobutton-color--disabled);color:var(--_nys-radiobutton-color--disabled)}fieldset{all:unset;display:contents}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;border:0}`;
|
|
15
|
+
var E = Object.defineProperty, d = (h, t, e, o) => {
|
|
16
|
+
for (var s = void 0, c = h.length - 1, u; c >= 0; c--)
|
|
17
|
+
(u = h[c]) && (s = u(t, e, s) || s);
|
|
18
|
+
return s && E(t, e, s), s;
|
|
9
19
|
};
|
|
10
20
|
let x = 0;
|
|
11
|
-
const
|
|
21
|
+
const p = class p extends f {
|
|
12
22
|
// allows use of elementInternals' API
|
|
13
23
|
constructor() {
|
|
14
24
|
super(), this.id = "", this.name = "", this.required = !1, this.optional = !1, this.showError = !1, this.errorMessage = "", this.label = "", this.description = "", this.tile = !1, this.tooltip = "", this.inverted = !1, this.form = null, this.size = "md", this.selectedValue = null, this._slottedDescriptionText = "", this._internals = this.attachInternals();
|
|
15
25
|
}
|
|
16
26
|
// Generate a unique ID if one is not provided
|
|
17
27
|
connectedCallback() {
|
|
18
|
-
super.connectedCallback(), this.id || (this.id = `nys-radiogroup-${Date.now()}-${x++}`), this.addEventListener("nys-change", this._handleRadioButtonChange), this.addEventListener("invalid", this._handleInvalid);
|
|
28
|
+
super.connectedCallback(), this.id || (this.id = `nys-radiogroup-${Date.now()}-${x++}`), this.addEventListener("nys-change", this._handleRadioButtonChange), this.addEventListener("invalid", this._handleInvalid), this.addEventListener("nys-error", this._handleChildError);
|
|
19
29
|
}
|
|
20
30
|
disconnectedCallback() {
|
|
21
31
|
super.disconnectedCallback(), this.removeEventListener("nys-change", this._handleRadioButtonChange), this.removeEventListener("invalid", this._handleInvalid);
|
|
@@ -66,25 +76,20 @@ const b = class b extends _ {
|
|
|
66
76
|
}
|
|
67
77
|
// Arrow / Space / Enter navigation at group level
|
|
68
78
|
async _handleKeyDown(t) {
|
|
69
|
-
if (![
|
|
70
|
-
"ArrowUp",
|
|
71
|
-
"ArrowDown",
|
|
72
|
-
"ArrowLeft",
|
|
73
|
-
"ArrowRight",
|
|
74
|
-
" ",
|
|
75
|
-
"Enter"
|
|
76
|
-
].includes(t.key)) return;
|
|
79
|
+
if (!["ArrowUp", "ArrowDown", " ", "Enter"].includes(t.key)) return;
|
|
77
80
|
t.preventDefault();
|
|
78
|
-
const o = this._getAllRadios().filter((y) => !y.disabled),
|
|
79
|
-
let
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
(
|
|
81
|
+
const o = this._getAllRadios().filter((y) => !y.disabled), c = o.find((y) => y.matches(":focus")) || o.find((y) => y.checked) || o[0];
|
|
82
|
+
let u = 0;
|
|
83
|
+
["ArrowUp", "ArrowLeft"].includes(t.key) ? u = -1 : ["ArrowDown", "ArrowRight"].includes(t.key) && (u = 1);
|
|
84
|
+
let b = o.indexOf(c) + u;
|
|
85
|
+
b < 0 && (b = o.length - 1), b >= o.length && (b = 0);
|
|
86
|
+
const g = o[b];
|
|
87
|
+
(await g.getInputElement())?.click(), await this.updateComplete, this._updateGroupTabIndex(), g.focus();
|
|
83
88
|
}
|
|
84
89
|
_updateGroupTabIndex() {
|
|
85
|
-
const t = this._getAllRadios(), e = t.find((o) => o.checked) || t
|
|
90
|
+
const t = this._getAllRadios(), e = t.find((o) => o.checked && !o.disabled) || t.find((o) => !o.disabled);
|
|
86
91
|
t.forEach((o) => {
|
|
87
|
-
o.
|
|
92
|
+
o.setAttribute("aria-checked", String(o.checked)), o.tabIndex = o === e && !o.disabled ? 0 : -1;
|
|
88
93
|
});
|
|
89
94
|
}
|
|
90
95
|
// This callback is automatically called when the parent form is reset.
|
|
@@ -142,11 +147,21 @@ const b = class b extends _ {
|
|
|
142
147
|
*/
|
|
143
148
|
// Keeps radiogroup informed of the name and value of its current selected radiobutton at each change
|
|
144
149
|
_handleRadioButtonChange(t) {
|
|
145
|
-
const
|
|
146
|
-
this.name =
|
|
150
|
+
const { name: e, value: o } = t.detail;
|
|
151
|
+
this.name = e, this.selectedValue = o, this._internals.setFormValue(this.selectedValue), this._internals.setValidity({}), this.showError = !1, this._updateGroupTabIndex();
|
|
147
152
|
}
|
|
148
153
|
async _handleInvalid(t) {
|
|
149
|
-
if (t.preventDefault(), this._internals.validity.
|
|
154
|
+
if (t.preventDefault(), this._internals.validity.customError) {
|
|
155
|
+
const o = this._getAllRadios().find((s) => s.other && s.checked);
|
|
156
|
+
if (o) {
|
|
157
|
+
const s = o.shadowRoot?.querySelector("nys-textinput");
|
|
158
|
+
if (o.classList.remove("focused"), s) {
|
|
159
|
+
await s.updateComplete, s.focus();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (this._internals.validity.valueMissing) {
|
|
150
165
|
this.showError = !0, this._manageRequire();
|
|
151
166
|
const e = this.querySelector(
|
|
152
167
|
"nys-radiobutton"
|
|
@@ -154,13 +169,26 @@ const b = class b extends _ {
|
|
|
154
169
|
if (e) {
|
|
155
170
|
const o = this._internals.form;
|
|
156
171
|
o ? Array.from(o.elements).find(
|
|
157
|
-
(
|
|
158
|
-
) === this &&
|
|
172
|
+
(u) => typeof u.checkValidity == "function" && !u.checkValidity()
|
|
173
|
+
) === this && e.focus() : e.focus();
|
|
159
174
|
}
|
|
160
175
|
}
|
|
161
176
|
}
|
|
177
|
+
_handleChildError(t) {
|
|
178
|
+
t.stopPropagation();
|
|
179
|
+
const { message: e, sourceRadio: o } = t.detail;
|
|
180
|
+
o && (this.showError = !0, this._internals.setValidity(
|
|
181
|
+
{ customError: !0 },
|
|
182
|
+
e || "Please complete this field.",
|
|
183
|
+
o
|
|
184
|
+
));
|
|
185
|
+
}
|
|
162
186
|
render() {
|
|
163
|
-
return v`<
|
|
187
|
+
return v`<fieldset
|
|
188
|
+
aria-label="${this.label}${this._slottedDescriptionText ? ` ${this._slottedDescriptionText}` : this.description ? ` ${this.description}` : ""}"
|
|
189
|
+
role="radiogroup"
|
|
190
|
+
class="nys-radiogroup"
|
|
191
|
+
>
|
|
164
192
|
<nys-label
|
|
165
193
|
for=${this.id + "--native"}
|
|
166
194
|
label=${this.label}
|
|
@@ -171,93 +199,93 @@ const b = class b extends _ {
|
|
|
171
199
|
>
|
|
172
200
|
<slot name="description" slot="description">${this.description}</slot>
|
|
173
201
|
</nys-label>
|
|
174
|
-
<div class="nys-radiogroup__content">
|
|
175
|
-
<
|
|
176
|
-
<legend class="sr-only">
|
|
177
|
-
${this.label}${this._slottedDescriptionText ? ` ${this._slottedDescriptionText}` : this.description ? ` ${this.description}` : ""}
|
|
178
|
-
</legend>
|
|
179
|
-
<slot></slot>
|
|
180
|
-
</fieldset>
|
|
202
|
+
<div class="nys-radiogroup__content" @keydown=${this._handleKeyDown}>
|
|
203
|
+
<slot></slot>
|
|
181
204
|
</div>
|
|
182
205
|
<nys-errormessage
|
|
183
206
|
?showError=${this.showError}
|
|
184
207
|
errorMessage=${this._internals.validationMessage || this.errorMessage}
|
|
185
208
|
.showDivider=${!this.tile}
|
|
186
209
|
></nys-errormessage>
|
|
187
|
-
</
|
|
210
|
+
</fieldset>`;
|
|
188
211
|
}
|
|
189
212
|
};
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
213
|
+
p.styles = k(w), p.shadowRootOptions = {
|
|
214
|
+
...f.shadowRootOptions,
|
|
215
|
+
delegatesFocus: !0
|
|
216
|
+
}, p.formAssociated = !0;
|
|
217
|
+
let n = p;
|
|
218
|
+
d([
|
|
193
219
|
r({ type: String, reflect: !0 })
|
|
194
220
|
], n.prototype, "id");
|
|
195
|
-
|
|
221
|
+
d([
|
|
196
222
|
r({ type: String, reflect: !0 })
|
|
197
223
|
], n.prototype, "name");
|
|
198
|
-
|
|
224
|
+
d([
|
|
199
225
|
r({ type: Boolean, reflect: !0 })
|
|
200
226
|
], n.prototype, "required");
|
|
201
|
-
|
|
227
|
+
d([
|
|
202
228
|
r({ type: Boolean, reflect: !0 })
|
|
203
229
|
], n.prototype, "optional");
|
|
204
|
-
|
|
230
|
+
d([
|
|
205
231
|
r({ type: Boolean, reflect: !0 })
|
|
206
232
|
], n.prototype, "showError");
|
|
207
|
-
|
|
233
|
+
d([
|
|
208
234
|
r({ type: String })
|
|
209
235
|
], n.prototype, "errorMessage");
|
|
210
|
-
|
|
236
|
+
d([
|
|
211
237
|
r({ type: String })
|
|
212
238
|
], n.prototype, "label");
|
|
213
|
-
|
|
239
|
+
d([
|
|
214
240
|
r({ type: String })
|
|
215
241
|
], n.prototype, "description");
|
|
216
|
-
|
|
242
|
+
d([
|
|
217
243
|
r({ type: Boolean, reflect: !0 })
|
|
218
244
|
], n.prototype, "tile");
|
|
219
|
-
|
|
245
|
+
d([
|
|
220
246
|
r({ type: String })
|
|
221
247
|
], n.prototype, "tooltip");
|
|
222
|
-
|
|
248
|
+
d([
|
|
223
249
|
r({ type: Boolean, reflect: !0 })
|
|
224
250
|
], n.prototype, "inverted");
|
|
225
|
-
|
|
251
|
+
d([
|
|
226
252
|
r({ type: String, reflect: !0 })
|
|
227
253
|
], n.prototype, "form");
|
|
228
|
-
|
|
254
|
+
d([
|
|
229
255
|
r({ type: String, reflect: !0 })
|
|
230
256
|
], n.prototype, "size");
|
|
231
|
-
|
|
257
|
+
d([
|
|
232
258
|
m()
|
|
233
259
|
], n.prototype, "selectedValue");
|
|
234
|
-
|
|
260
|
+
d([
|
|
235
261
|
m()
|
|
236
262
|
], n.prototype, "_slottedDescriptionText");
|
|
237
263
|
customElements.get("nys-radiogroup") || customElements.define("nys-radiogroup", n);
|
|
238
|
-
var
|
|
239
|
-
for (var s = void 0, c = h.length - 1,
|
|
240
|
-
(
|
|
241
|
-
return s &&
|
|
264
|
+
var A = Object.defineProperty, l = (h, t, e, o) => {
|
|
265
|
+
for (var s = void 0, c = h.length - 1, u; c >= 0; c--)
|
|
266
|
+
(u = h[c]) && (s = u(t, e, s) || s);
|
|
267
|
+
return s && A(t, e, s), s;
|
|
242
268
|
};
|
|
243
|
-
let
|
|
269
|
+
let B = 0;
|
|
244
270
|
var i;
|
|
245
|
-
const
|
|
271
|
+
const a = (i = class extends f {
|
|
246
272
|
constructor() {
|
|
247
|
-
super(...arguments), this.checked = !1, this.disabled = !1, this.required = !1, this.label = "", this.description = "", this.id = "", this.name = "", this.value = "", this.inverted = !1, this.form = null, this.size = "md", this.tile = !1
|
|
273
|
+
super(...arguments), this.checked = !1, this.disabled = !1, this.required = !1, this.label = "", this.description = "", this.id = "", this.name = "", this.value = "", this.inverted = !1, this.form = null, this.size = "md", this.tile = !1, this.other = !1, this.showOtherError = !1, this.isMobile = window.innerWidth < 480, this._hasUserInteracted = !1, this._handleResize = () => {
|
|
274
|
+
this.isMobile = window.innerWidth < 480;
|
|
275
|
+
};
|
|
248
276
|
}
|
|
249
277
|
/**
|
|
250
278
|
* Lifecycle methods
|
|
251
279
|
* --------------------------------------------------------------------------
|
|
252
280
|
*/
|
|
253
281
|
connectedCallback() {
|
|
254
|
-
super.connectedCallback(), this.id || (this.id = `nys-radiobutton-${Date.now()}-${
|
|
282
|
+
super.connectedCallback(), this.id || (this.id = `nys-radiobutton-${Date.now()}-${B++}`), this.checked && (i.buttonGroup[this.name] && (i.buttonGroup[this.name].checked = !1, i.buttonGroup[this.name].requestUpdate()), i.buttonGroup[this.name] = this), this.addEventListener("focus", this._handleFocus), this.addEventListener("blur", this._handleBlur), this.addEventListener("click", this._handleChange), window.addEventListener("resize", this._handleResize);
|
|
255
283
|
}
|
|
256
284
|
disconnectedCallback() {
|
|
257
|
-
super.disconnectedCallback(), this.removeEventListener("focus", this._handleFocus), this.removeEventListener("blur", this._handleBlur);
|
|
285
|
+
super.disconnectedCallback(), this.removeEventListener("focus", this._handleFocus), this.removeEventListener("blur", this._handleBlur), window.removeEventListener("resize", this._handleResize);
|
|
258
286
|
}
|
|
259
287
|
updated(t) {
|
|
260
|
-
t.has("checked") && this.checked && i.buttonGroup[this.name] !== this && (i.buttonGroup[this.name] && (i.buttonGroup[this.name].checked = !1, i.buttonGroup[this.name].requestUpdate()), i.buttonGroup[this.name] = this);
|
|
288
|
+
t.has("checked") && (t.get("checked") && !this.checked && this._clearOtherState(), this.checked && i.buttonGroup[this.name] !== this && (i.buttonGroup[this.name] && (i.buttonGroup[this.name].checked = !1, i.buttonGroup[this.name].requestUpdate()), i.buttonGroup[this.name] = this));
|
|
261
289
|
}
|
|
262
290
|
/**
|
|
263
291
|
* Functions
|
|
@@ -268,7 +296,20 @@ const l = (i = class extends _ {
|
|
|
268
296
|
}
|
|
269
297
|
// This callback is automatically called when the parent form is reset.
|
|
270
298
|
formResetUpdate() {
|
|
271
|
-
this.checked = !1, this.
|
|
299
|
+
this.checked = !1, this._clearOtherState(), i.buttonGroup[this.name] === this && delete i.buttonGroup[this.name], this.requestUpdate();
|
|
300
|
+
}
|
|
301
|
+
_clearOtherState() {
|
|
302
|
+
this.other && (this.showOtherError = !1, this._hasUserInteracted = !1, this.dispatchEvent(
|
|
303
|
+
new CustomEvent("nys-error-clear", {
|
|
304
|
+
detail: {
|
|
305
|
+
id: this.id,
|
|
306
|
+
name: this.name,
|
|
307
|
+
type: "other"
|
|
308
|
+
},
|
|
309
|
+
bubbles: !0,
|
|
310
|
+
composed: !0
|
|
311
|
+
})
|
|
312
|
+
));
|
|
272
313
|
}
|
|
273
314
|
/**
|
|
274
315
|
* Event Handlers
|
|
@@ -288,9 +329,22 @@ const l = (i = class extends _ {
|
|
|
288
329
|
})
|
|
289
330
|
);
|
|
290
331
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
332
|
+
_emitOtherInputEvent() {
|
|
333
|
+
this.dispatchEvent(
|
|
334
|
+
new CustomEvent("nys-other-input", {
|
|
335
|
+
detail: {
|
|
336
|
+
id: this.id,
|
|
337
|
+
name: this.name,
|
|
338
|
+
value: this.value
|
|
339
|
+
},
|
|
340
|
+
bubbles: !0,
|
|
341
|
+
composed: !0
|
|
342
|
+
})
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
// Handle radiobutton change event & un-selection of other radio options in group
|
|
346
|
+
async _handleChange() {
|
|
347
|
+
this.showOtherError = !1, !this.checked && !this.disabled && (i.buttonGroup[this.name] && (i.buttonGroup[this.name].checked = !1, i.buttonGroup[this.name].requestUpdate()), i.buttonGroup[this.name] = this, this.checked = !0, this._validateOtherAndEmitError(), this._emitChangeEvent());
|
|
294
348
|
}
|
|
295
349
|
// Handle focus event
|
|
296
350
|
_handleFocus() {
|
|
@@ -298,7 +352,9 @@ const l = (i = class extends _ {
|
|
|
298
352
|
}
|
|
299
353
|
// Handle blur event
|
|
300
354
|
_handleBlur() {
|
|
301
|
-
this.
|
|
355
|
+
this.dispatchEvent(new Event("nys-blur")), setTimeout(() => {
|
|
356
|
+
this.other && this.checked && (this._hasUserInteracted = !0, this._validateOtherAndEmitError());
|
|
357
|
+
}, 50);
|
|
302
358
|
}
|
|
303
359
|
_callInputHandling() {
|
|
304
360
|
if (this.disabled) return;
|
|
@@ -307,77 +363,140 @@ const l = (i = class extends _ {
|
|
|
307
363
|
);
|
|
308
364
|
t && (t.focus(), t.click());
|
|
309
365
|
}
|
|
366
|
+
_handleTextInput(t) {
|
|
367
|
+
let o = t.target.value;
|
|
368
|
+
this.value = o, this._hasUserInteracted && this._validateOtherAndEmitError(), this._emitOtherInputEvent();
|
|
369
|
+
}
|
|
370
|
+
_handleTextInputBlur() {
|
|
371
|
+
this._hasUserInteracted = !0, this._validateOtherAndEmitError();
|
|
372
|
+
}
|
|
373
|
+
_validateOtherAndEmitError() {
|
|
374
|
+
if (!this.other) return;
|
|
375
|
+
if (!this.checked || !this._hasUserInteracted) {
|
|
376
|
+
this.showOtherError = !1;
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
const t = this.value.trim() === "";
|
|
380
|
+
this.showOtherError = t, t && this.dispatchEvent(
|
|
381
|
+
new CustomEvent("nys-error", {
|
|
382
|
+
detail: {
|
|
383
|
+
id: this.id,
|
|
384
|
+
name: this.name,
|
|
385
|
+
type: "other",
|
|
386
|
+
message: "Please enter a value for this option.",
|
|
387
|
+
sourceRadio: this
|
|
388
|
+
},
|
|
389
|
+
bubbles: !0,
|
|
390
|
+
composed: !0
|
|
391
|
+
})
|
|
392
|
+
);
|
|
393
|
+
}
|
|
394
|
+
_handleOtherKeydown(t) {
|
|
395
|
+
(t.key == "Space" || t.key === " ") && t.stopPropagation();
|
|
396
|
+
}
|
|
310
397
|
render() {
|
|
311
398
|
return v`
|
|
312
399
|
<input
|
|
313
400
|
type="radio"
|
|
314
|
-
name="${
|
|
401
|
+
name="${_(this.name ? this.name : void 0)}"
|
|
315
402
|
.checked=${this.checked}
|
|
316
403
|
?disabled=${this.disabled}
|
|
317
404
|
.value=${this.value}
|
|
318
405
|
?required="${this.required}"
|
|
319
|
-
form=${
|
|
406
|
+
form=${_(this.form || void 0)}
|
|
320
407
|
@change="${this._handleChange}"
|
|
321
|
-
hidden
|
|
322
408
|
aria-hidden="true"
|
|
409
|
+
hidden
|
|
410
|
+
class="sr-only"
|
|
323
411
|
/>
|
|
324
412
|
<div
|
|
325
413
|
class="nys-radiobutton"
|
|
326
414
|
@click="${this._callInputHandling}"
|
|
327
|
-
aria-label=${this.label}
|
|
415
|
+
aria-label=${this.label || (this.other ?? "Other")}
|
|
328
416
|
>
|
|
329
|
-
<
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
417
|
+
<div class="nys-radiobutton__main-container">
|
|
418
|
+
<span class="nys-radiobutton__radio"></span>
|
|
419
|
+
${(this.label || this.other) && v`<nys-label
|
|
420
|
+
label="${this.label || (this.other ? "Other" : "")}"
|
|
421
|
+
description=${_(this.description || void 0)}
|
|
422
|
+
?inverted=${this.inverted}
|
|
423
|
+
>
|
|
424
|
+
<slot name="description" slot="description"
|
|
425
|
+
>${this.description}</slot
|
|
426
|
+
>
|
|
427
|
+
</nys-label> `}
|
|
428
|
+
</div>
|
|
429
|
+
<div class="nys-radiobutton__other-container">
|
|
430
|
+
${this.other && this.checked ? v`
|
|
431
|
+
<nys-textinput
|
|
432
|
+
.value=${this.value}
|
|
433
|
+
id=${"radiobutton-other-" + this.id}
|
|
434
|
+
@nys-input=${this._handleTextInput}
|
|
435
|
+
@nys-blur=${this._handleTextInputBlur}
|
|
436
|
+
@keydown=${this._handleOtherKeydown}
|
|
437
|
+
@nys-focus=${() => this.classList.remove("focused")}
|
|
438
|
+
ariaLabel="Other"
|
|
439
|
+
aria-invalid=${this.showOtherError ? "true" : "false"}
|
|
440
|
+
width=${this.isMobile ? "full" : "md"}
|
|
441
|
+
></nys-textinput>
|
|
442
|
+
` : ""}
|
|
443
|
+
</div>
|
|
337
444
|
</div>
|
|
338
445
|
`;
|
|
339
446
|
}
|
|
340
|
-
}, i.styles =
|
|
341
|
-
|
|
447
|
+
}, i.styles = k(w), i.shadowRootOptions = {
|
|
448
|
+
...f.shadowRootOptions,
|
|
449
|
+
delegatesFocus: !0
|
|
450
|
+
}, i.buttonGroup = {}, i);
|
|
451
|
+
l([
|
|
342
452
|
r({ type: Boolean, reflect: !0 })
|
|
343
|
-
],
|
|
344
|
-
|
|
453
|
+
], a.prototype, "checked");
|
|
454
|
+
l([
|
|
345
455
|
r({ type: Boolean, reflect: !0 })
|
|
346
|
-
],
|
|
347
|
-
|
|
456
|
+
], a.prototype, "disabled");
|
|
457
|
+
l([
|
|
348
458
|
r({ type: Boolean, reflect: !0 })
|
|
349
|
-
],
|
|
350
|
-
|
|
459
|
+
], a.prototype, "required");
|
|
460
|
+
l([
|
|
351
461
|
r({ type: String })
|
|
352
|
-
],
|
|
353
|
-
|
|
462
|
+
], a.prototype, "label");
|
|
463
|
+
l([
|
|
354
464
|
r({ type: String })
|
|
355
|
-
],
|
|
356
|
-
|
|
465
|
+
], a.prototype, "description");
|
|
466
|
+
l([
|
|
357
467
|
r({ type: String, reflect: !0 })
|
|
358
|
-
],
|
|
359
|
-
|
|
468
|
+
], a.prototype, "id");
|
|
469
|
+
l([
|
|
360
470
|
r({ type: String, reflect: !0 })
|
|
361
|
-
],
|
|
362
|
-
|
|
471
|
+
], a.prototype, "name");
|
|
472
|
+
l([
|
|
363
473
|
r({ type: String })
|
|
364
|
-
],
|
|
365
|
-
|
|
474
|
+
], a.prototype, "value");
|
|
475
|
+
l([
|
|
366
476
|
r({ type: Boolean, reflect: !0 })
|
|
367
|
-
],
|
|
368
|
-
|
|
477
|
+
], a.prototype, "inverted");
|
|
478
|
+
l([
|
|
369
479
|
r({ type: String, reflect: !0 })
|
|
370
|
-
],
|
|
371
|
-
|
|
480
|
+
], a.prototype, "form");
|
|
481
|
+
l([
|
|
372
482
|
r({ type: String, reflect: !0 })
|
|
373
|
-
],
|
|
374
|
-
|
|
483
|
+
], a.prototype, "size");
|
|
484
|
+
l([
|
|
375
485
|
r({ type: Boolean, reflect: !0 })
|
|
376
|
-
],
|
|
377
|
-
|
|
378
|
-
|
|
486
|
+
], a.prototype, "tile");
|
|
487
|
+
l([
|
|
488
|
+
r({ type: Boolean, reflect: !0 })
|
|
489
|
+
], a.prototype, "other");
|
|
490
|
+
l([
|
|
491
|
+
r({ type: Boolean })
|
|
492
|
+
], a.prototype, "showOtherError");
|
|
493
|
+
l([
|
|
494
|
+
m()
|
|
495
|
+
], a.prototype, "isMobile");
|
|
496
|
+
let R = a;
|
|
497
|
+
customElements.get("nys-radiobutton") || customElements.define("nys-radiobutton", R);
|
|
379
498
|
export {
|
|
380
|
-
|
|
499
|
+
R as NysRadiobutton,
|
|
381
500
|
n as NysRadiogroup
|
|
382
501
|
};
|
|
383
502
|
//# sourceMappingURL=nys-radiobutton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nys-radiobutton.js","sources":["../src/nys-radiogroup.ts","../src/nys-radiobutton.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport type { NysRadiobutton } from \"./nys-radiobutton\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-radiobutton.scss?inline\";\n\nlet radiogroupIdCounter = 0;\n\n/**\n * A container for grouping `nys-radiobutton` elements as a single form control with enforced single selection.\n * Handles keyboard navigation (arrow keys), validation, required constraints, and form integration.\n *\n * Use to let users select exactly one option from 2-6 choices. Apply `tile`, `size`, and `inverted` to the group\n * and all children inherit these styles automatically. For 7+ options, use `nys-select`.\n *\n * @summary Container for grouping radio buttons as a single form control.\n * @element nys-radiogroup\n *\n * @slot - Default slot for `nys-radiobutton` elements.\n * @slot description - Custom HTML description content.\n *\n * @example Basic radio group\n * ```html\n * <nys-radiogroup label=\"Select borough\" required>\n * <nys-radiobutton name=\"borough\" value=\"bronx\" label=\"The Bronx\"></nys-radiobutton>\n * <nys-radiobutton name=\"borough\" value=\"brooklyn\" label=\"Brooklyn\"></nys-radiobutton>\n * <nys-radiobutton name=\"borough\" value=\"manhattan\" label=\"Manhattan\"></nys-radiobutton>\n * </nys-radiogroup>\n * ```\n */\n\nexport class NysRadiogroup extends LitElement {\n static styles = unsafeCSS(styles);\n\n /** Unique identifier. Auto-generated if not provided. */\n @property({ type: String, reflect: true }) id = \"\";\n\n /** Name for form submission. Auto-populated from child radiobuttons. */\n @property({ type: String, reflect: true }) name = \"\";\n\n /** Requires a selection before form submission. */\n @property({ type: Boolean, reflect: true }) required = false;\n\n /** Shows \"Optional\" flag. */\n @property({ type: Boolean, reflect: true }) optional = false;\n\n /** Shows error message when true. */\n @property({ type: Boolean, reflect: true }) showError = false;\n\n /** Error message text. Shown only when `showError` is true. */\n @property({ type: String }) errorMessage = \"\";\n\n /** Visible label text for the group. */\n @property({ type: String }) label = \"\";\n\n /** Helper text below label. Use slot for custom HTML. */\n @property({ type: String }) description = \"\";\n\n /** Renders all radiobuttons as tiles with larger clickable area. */\n @property({ type: Boolean, reflect: true }) tile = false;\n\n /** Tooltip text shown on hover/focus of info icon. */\n @property({ type: String }) tooltip = \"\";\n\n /** Adjusts colors for dark backgrounds. Applied to all children. */\n @property({ type: Boolean, reflect: true }) inverted = false;\n\n /** Form `id` to associate with. Applied to all children. */\n @property({ type: String, reflect: true }) form: string | null = null;\n\n /**\n * Radio size for all children: `sm` (24px) or `md` (32px, default).\n * @default \"md\"\n */\n @property({ type: String, reflect: true }) size: \"sm\" | \"md\" = \"md\";\n\n @state() private selectedValue: string | null = null;\n @state() private _slottedDescriptionText = \"\";\n\n private _internals: ElementInternals;\n\n /**\n * Lifecycle methods\n * --------------------------------------------------------------------------\n */\n\n static formAssociated = true; // allows use of elementInternals' API\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n // Generate a unique ID if one is not provided\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-radiogroup-${Date.now()}-${radiogroupIdCounter++}`;\n }\n this.addEventListener(\"nys-change\", this._handleRadioButtonChange);\n this.addEventListener(\"invalid\", this._handleInvalid);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"nys-change\", this._handleRadioButtonChange);\n this.removeEventListener(\"invalid\", this._handleInvalid);\n }\n\n async firstUpdated() {\n await this.updateComplete;\n this._initializeCheckedRadioValue();\n this._setValue(); // This ensures our element always participates in the form\n this._setRadioButtonRequire();\n this._updateRadioButtonsSize();\n this._updateRadioButtonsTile();\n this._updateRadioButtonsShowError();\n this._getSlotDescriptionForAria();\n\n this._initializeChildAttributes();\n this._updateGroupTabIndex();\n }\n\n updated(changedProperties: Map<string | symbol, unknown>) {\n if (\n changedProperties.has(\"required\") ||\n changedProperties.has(\"selectedValue\")\n ) {\n this._manageRequire();\n }\n if (changedProperties.has(\"size\")) {\n this._updateRadioButtonsSize();\n }\n if (changedProperties.has(\"tile\")) {\n this._updateRadioButtonsTile();\n }\n if (changedProperties.has(\"inverted\")) {\n this._updateRadioButtonsInvert();\n }\n if (changedProperties.has(\"showError\")) {\n this._updateRadioButtonsShowError();\n }\n if (changedProperties.has(\"form\")) {\n this._updateRadioButtonsForm();\n }\n }\n\n /**\n * Form Integration\n * --------------------------------------------------------------------------\n */\n\n private _setValue() {\n this._internals.setFormValue(this.selectedValue);\n }\n\n // Updates the \"require\" attribute of the first radiobutton underneath a radiogroup.\n // This will make sure there's a requirement for all radiobutton under the same name/group\n private _setRadioButtonRequire() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton, index) => {\n if (this.required && index === 0) {\n radioButton.setAttribute(\"required\", \"required\");\n }\n });\n }\n\n private async _manageRequire() {\n const message = this.errorMessage || \"Please select an option.\";\n\n const radioButtons = Array.from(this.querySelectorAll(\"nys-radiobutton\"));\n const firstRadio = radioButtons[0] as HTMLElement;\n\n if (firstRadio) {\n if (this.required && !this.selectedValue) {\n this._internals.setValidity(\n { valueMissing: true },\n message,\n firstRadio, // pass the custom element, not shadow input\n );\n } else {\n this.showError = false;\n this._internals.setValidity({}, \"\", firstRadio);\n }\n }\n }\n\n checkValidity() {\n const radioButtons = Array.from(this.querySelectorAll(\"nys-radiobutton\"));\n const valid =\n !this.required ||\n radioButtons.some((radio) => (radio as NysRadiobutton).checked);\n return valid;\n }\n\n // Need to account for if radiogroup already have a radiobutton checked at initialization\n private _initializeCheckedRadioValue() {\n const checkedRadio = this.querySelector(\"nys-radiobutton[checked]\");\n if (checkedRadio) {\n this.selectedValue = checkedRadio.getAttribute(\"value\");\n this._internals.setFormValue(this.selectedValue);\n }\n }\n\n // Core Keyboard & Click Logic\n private _getAllRadios() {\n return Array.from(\n this.querySelectorAll(\"nys-radiobutton\"),\n ) as NysRadiobutton[];\n }\n\n // Arrow / Space / Enter navigation at group level\n private async _handleKeyDown(event: KeyboardEvent) {\n const keys = [\n \"ArrowUp\",\n \"ArrowDown\",\n \"ArrowLeft\",\n \"ArrowRight\",\n \" \",\n \"Enter\",\n ];\n\n if (!keys.includes(event.key)) return;\n event.preventDefault();\n\n const radioBtns = this._getAllRadios().filter((radio) => !radio.disabled);\n const checkedRadio =\n radioBtns.find((radio) => radio.checked) || radioBtns[0];\n\n // Computing the new index based on the keydown event\n const increment =\n event.key === \" \" || event.key === \"Enter\"\n ? 0\n : [\"ArrowUp\", \"ArrowLeft\"].includes(event.key)\n ? -1\n : 1;\n\n let index = radioBtns.indexOf(checkedRadio) + increment;\n // Handles the wrap around ends if user is at first or last radiobutton\n if (index < 0) {\n index = radioBtns.length - 1;\n }\n if (index >= radioBtns.length) {\n index = 0;\n }\n\n // The target is the new radiobutton the user want to choose given the keydown type.\n // We let the target's <input/> dispatch the clickEvent and call _handleRadioButtonChange() directly to make form integration work\n const target = radioBtns[index];\n const input = await target.getInputElement();\n input?.click();\n\n this._updateGroupTabIndex();\n target.focus();\n }\n\n private _updateGroupTabIndex() {\n const radios = this._getAllRadios();\n const active = radios.find((radio) => radio.checked) || radios[0]; // If none checked, make first radiobutton tabbable\n\n radios.forEach((radio) => {\n if (radio.disabled) {\n radio.tabIndex = -1;\n } else {\n radio.tabIndex = radio === active ? 0 : -1;\n }\n\n // Need to update ARIA state due to the new tabindex\n radio.setAttribute(\"aria-checked\", radio.checked ? \"true\" : \"false\");\n radio.setAttribute(\"aria-disabled\", radio.disabled ? \"true\" : \"false\");\n radio.setAttribute(\"aria-required\", this.required ? \"true\" : \"false\");\n });\n }\n\n // This callback is automatically called when the parent form is reset.\n public formResetCallback() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n (radioButton as NysRadiobutton).formResetUpdate();\n });\n\n this.selectedValue = null;\n\n this._internals.setFormValue(null);\n\n // Reset validation UI\n this.showError = false;\n this.errorMessage = \"\";\n this._internals.setValidity({});\n\n // Re-render UI\n this.requestUpdate();\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n // Apply ARIA & initial tabindex to each child radio\n private _initializeChildAttributes() {\n const radios = this._getAllRadios();\n radios.forEach((radio) => {\n radio.setAttribute(\"role\", \"radio\");\n radio.setAttribute(\"aria-checked\", String(radio.checked));\n radio.setAttribute(\"aria-required\", String(radio.required));\n radio.setAttribute(\"aria-disabled\", String(radio.disabled));\n radio.setAttribute(\"tabindex\", \"-1\");\n });\n }\n\n // Updates the size of each radiobutton underneath a radiogroup to ensure size standardization\n private _updateRadioButtonsSize() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n radioButton.setAttribute(\"size\", this.size);\n });\n }\n\n private _updateRadioButtonsTile() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n if (this.tile) {\n radioButton.toggleAttribute(\"tile\", true);\n } else {\n radioButton.removeAttribute(\"tile\");\n }\n });\n }\n\n private _updateRadioButtonsInvert() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n if (this.inverted) {\n radioButton.toggleAttribute(\"inverted\", true);\n } else {\n radioButton.removeAttribute(\"inverted\");\n }\n });\n }\n\n private _updateRadioButtonsShowError() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n if (this.showError) {\n radioButton.setAttribute(\"showError\", \"\");\n } else {\n radioButton.removeAttribute(\"showError\");\n }\n });\n }\n\n private _updateRadioButtonsForm() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n if (this.showError) {\n if (this.form !== null) {\n radioButton.setAttribute(\"form\", this.form);\n } else {\n radioButton.removeAttribute(\"form\");\n }\n } else {\n radioButton.removeAttribute(\"form\");\n }\n });\n }\n\n // Get the slotted text contents so native VO can attempt to announce it within the legend in the fieldset\n private _getSlotDescriptionForAria() {\n const slot = this.shadowRoot?.querySelector(\n 'slot[name=\"description\"]',\n ) as HTMLSlotElement;\n const nodes = slot?.assignedNodes({ flatten: true }) || [];\n\n this._slottedDescriptionText = nodes\n .map((node) => node.textContent?.trim())\n .filter(Boolean)\n .join(\", \");\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n // Keeps radiogroup informed of the name and value of its current selected radiobutton at each change\n private _handleRadioButtonChange(event: Event) {\n const customEvent = event as CustomEvent;\n const { name, value } = customEvent.detail;\n\n this.name = name;\n this.selectedValue = value;\n this._internals.setFormValue(this.selectedValue);\n\n // Accounts for tabindex & ARIA on every click/space select\n this._updateGroupTabIndex();\n }\n\n private async _handleInvalid(event: Event) {\n event.preventDefault();\n\n // Check if the radio group is invalid and set `showError` accordingly\n if (this._internals.validity.valueMissing) {\n this.showError = true;\n this._manageRequire(); // Refresh validation message\n\n const firstRadio = this.querySelector(\n \"nys-radiobutton\",\n ) as NysRadiobutton;\n\n if (firstRadio) {\n // Focus only if this is the first invalid element (top-down approach)\n const form = this._internals.form;\n if (form) {\n const elements = Array.from(form.elements) as Array<\n HTMLElement & { checkValidity?: () => boolean }\n >;\n\n // Find the first element in the form that is invalid\n const firstInvalidElement = elements.find(\n (element) =>\n typeof element.checkValidity === \"function\" &&\n !element.checkValidity(),\n );\n if (firstInvalidElement === this) {\n firstRadio.focus();\n firstRadio.classList.add(\"active-focus\"); // Needed to show focus outline; will be removed if user clicks to select\n }\n } else {\n // If not part of a form, simply focus.\n firstRadio.focus();\n firstRadio.classList.add(\"active-focus\");\n }\n }\n }\n }\n\n render() {\n return html`<div class=\"nys-radiogroup\">\n <nys-label\n for=${this.id + \"--native\"}\n label=${this.label}\n description=${this.description}\n flag=${this.required ? \"required\" : this.optional ? \"optional\" : \"\"}\n tooltip=${this.tooltip}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\">${this.description}</slot>\n </nys-label>\n <div class=\"nys-radiogroup__content\">\n <fieldset role=\"radiogroup\" @keydown=${this._handleKeyDown}>\n <legend class=\"sr-only\">\n ${this.label}${this._slottedDescriptionText\n ? ` ${this._slottedDescriptionText}`\n : this.description\n ? ` ${this.description}`\n : \"\"}\n </legend>\n <slot></slot>\n </fieldset>\n </div>\n <nys-errormessage\n ?showError=${this.showError}\n errorMessage=${this._internals.validationMessage || this.errorMessage}\n .showDivider=${!this.tile}\n ></nys-errormessage>\n </div>`;\n }\n}\n\nif (!customElements.get(\"nys-radiogroup\")) {\n customElements.define(\"nys-radiogroup\", NysRadiogroup);\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport \"./nys-radiogroup\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-radiobutton.scss?inline\";\n\nlet radiobuttonIdCounter = 0;\n\n/**\n * A radio button for single selection within a `nys-radiogroup`. Only one radio with the same `name` can be selected.\n *\n * Use within `nys-radiogroup` for 2-6 mutually exclusive options. For 7+ options, use `nys-select`.\n * For multiple selections, use `nys-checkbox`.\n *\n * @summary Radio button for single selection from mutually exclusive options.\n * @element nys-radiobutton\n *\n * @slot description - Custom HTML description content.\n *\n * @fires nys-change - Fired when selection changes. Detail: `{id, checked, name, value}`.\n * @fires nys-focus - Fired when radio gains focus.\n * @fires nys-blur - Fired when radio loses focus.\n *\n * @example Radio group\n * ```html\n * <nys-radiogroup label=\"Select borough\" required>\n * <nys-radiobutton name=\"borough\" value=\"bronx\" label=\"The Bronx\"></nys-radiobutton>\n * <nys-radiobutton name=\"borough\" value=\"brooklyn\" label=\"Brooklyn\"></nys-radiobutton>\n * </nys-radiogroup>\n * ```\n */\n\nexport class NysRadiobutton extends LitElement {\n static styles = unsafeCSS(styles);\n\n /** Whether this radio is selected. Only one per group can be checked. */\n @property({ type: Boolean, reflect: true }) checked = false;\n\n /** Prevents interaction. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n /** Marks group as required. Set on radiogroup, not individual radios. */\n @property({ type: Boolean, reflect: true }) required = false;\n\n /** Visible label text. Required for accessibility. */\n @property({ type: String }) label = \"\";\n\n /** Helper text below label. Use slot for custom HTML. */\n @property({ type: String }) description = \"\";\n\n /** Unique identifier. Auto-generated if not provided. */\n @property({ type: String, reflect: true }) id = \"\";\n\n /** Group name. Radios with same name are mutually exclusive. */\n @property({ type: String, reflect: true }) name = \"\";\n\n /** Value submitted when this radio is selected. */\n @property({ type: String }) value = \"\";\n\n /** Adjusts colors for dark backgrounds. */\n @property({ type: Boolean, reflect: true }) inverted = false;\n\n /** Form `id` to associate with. */\n @property({ type: String, reflect: true }) form: string | null = null;\n\n /**\n * Radio size: `sm` (24px) or `md` (32px, default).\n * @default \"md\"\n */\n @property({ type: String, reflect: true }) size: \"sm\" | \"md\" = \"md\";\n\n /** Renders as tile with larger clickable area. */\n @property({ type: Boolean, reflect: true }) tile = false;\n\n static buttonGroup: Record<string, NysRadiobutton> = {};\n\n /**\n * Lifecycle methods\n * --------------------------------------------------------------------------\n */\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-radiobutton-${Date.now()}-${radiobuttonIdCounter++}`;\n }\n\n // If this button is initially checked, set it as the current button in its group\n if (this.checked) {\n if (NysRadiobutton.buttonGroup[this.name]) {\n NysRadiobutton.buttonGroup[this.name].checked = false;\n NysRadiobutton.buttonGroup[this.name].requestUpdate();\n }\n NysRadiobutton.buttonGroup[this.name] = this;\n }\n\n this.addEventListener(\"focus\", this._handleFocus);\n this.addEventListener(\"blur\", this._handleBlur);\n this.addEventListener(\"click\", this._handleChange);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n this.removeEventListener(\"focus\", this._handleFocus);\n this.removeEventListener(\"blur\", this._handleBlur);\n }\n\n updated(changedProperties: Map<string | number | symbol, unknown>) {\n // When \"checked\" changes, update the internals.\n if (changedProperties.has(\"checked\")) {\n // Ensure only one radiobutton per group is checked.\n if (this.checked && NysRadiobutton.buttonGroup[this.name] !== this) {\n if (NysRadiobutton.buttonGroup[this.name]) {\n NysRadiobutton.buttonGroup[this.name].checked = false;\n NysRadiobutton.buttonGroup[this.name].requestUpdate();\n }\n NysRadiobutton.buttonGroup[this.name] = this;\n }\n }\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n public async getInputElement(): Promise<HTMLInputElement | null> {\n await this.updateComplete; // Wait for the component to finish rendering\n return this.shadowRoot?.querySelector(\"input\") || null;\n }\n\n // This callback is automatically called when the parent form is reset.\n public formResetUpdate() {\n this.checked = false;\n\n this.setAttribute(\"aria-checked\", \"false\");\n\n if (NysRadiobutton.buttonGroup[this.name] === this) {\n delete NysRadiobutton.buttonGroup[this.name];\n }\n\n // Re-render UI\n this.requestUpdate();\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n private _emitChangeEvent() {\n this.dispatchEvent(\n new CustomEvent(\"nys-change\", {\n detail: {\n id: this.id,\n checked: this.checked,\n name: this.name,\n value: this.value,\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n // Handle radiobutton change event & unselection of other options in group\n private _handleChange() {\n // Remove active-focus so the focus outline doesn't linger\n // when the user selects a choice, since form focus is no longer needed\n this.classList.remove(\"active-focus\");\n\n if (!this.checked && !this.disabled) {\n if (NysRadiobutton.buttonGroup[this.name]) {\n NysRadiobutton.buttonGroup[this.name].checked = false;\n NysRadiobutton.buttonGroup[this.name].requestUpdate();\n }\n\n NysRadiobutton.buttonGroup[this.name] = this;\n this.checked = true;\n\n // Dispatch a change event with the name and value\n this._emitChangeEvent();\n }\n }\n\n // Handle focus event\n private _handleFocus() {\n this.dispatchEvent(new Event(\"nys-focus\"));\n }\n\n // Handle blur event\n private _handleBlur() {\n this.classList.remove(\"active-focus\"); // removing this classList so the focus ring for handleInvalid() at radiogroup level will disappear\n this.dispatchEvent(new Event(\"nys-blur\"));\n }\n\n private _callInputHandling() {\n if (this.disabled) return;\n\n // Find the hidden input and trigger a click to toggle selection\n const input = this.shadowRoot?.querySelector(\n 'input[type=\"radio\"]',\n ) as HTMLInputElement;\n\n if (input) {\n input.focus();\n input.click();\n }\n }\n\n render() {\n return html`\n <input\n type=\"radio\"\n name=\"${ifDefined(this.name ? this.name : undefined)}\"\n .checked=${this.checked}\n ?disabled=${this.disabled}\n .value=${this.value}\n ?required=\"${this.required}\"\n form=${ifDefined(this.form || undefined)}\n @change=\"${this._handleChange}\"\n hidden\n aria-hidden=\"true\"\n />\n <div\n class=\"nys-radiobutton\"\n @click=\"${this._callInputHandling}\"\n aria-label=${this.label}\n >\n <span class=\"nys-radiobutton__radio\"></span>\n ${this.label &&\n html`<nys-label\n label=${this.label}\n description=${ifDefined(this.description || undefined)}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\">${this.description}</slot>\n </nys-label> `}\n </div>\n `;\n }\n}\n\nif (!customElements.get(\"nys-radiobutton\")) {\n customElements.define(\"nys-radiobutton\", NysRadiobutton);\n}\n"],"names":["radiogroupIdCounter","_NysRadiogroup","LitElement","changedProperties","radioButton","index","message","firstRadio","radioButtons","radio","checkedRadio","event","radioBtns","increment","target","radios","active","nodes","node","customEvent","name","value","form","element","html","unsafeCSS","styles","NysRadiogroup","__decorateClass","property","state","radiobuttonIdCounter","_NysRadiobutton","_a","input","ifDefined","NysRadiobutton"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nys-radiobutton.js","sources":["../src/nys-radiogroup.ts","../src/nys-radiobutton.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport type { NysRadiobutton } from \"./nys-radiobutton\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-radiobutton.scss?inline\";\n\nlet radiogroupIdCounter = 0;\n\n/**\n * A container for grouping `nys-radiobutton` elements as a single form control with enforced single selection.\n * Handles keyboard navigation (arrow keys), validation, required constraints, and form integration.\n *\n * Use to let users select exactly one option from 2-6 choices. Apply `tile`, `size`, and `inverted` to the group\n * and all children inherit these styles automatically. For 7+ options, use `nys-select`.\n *\n * @summary Container for grouping radio buttons as a single form control.\n * @element nys-radiogroup\n *\n * @slot - Default slot for `nys-radiobutton` elements.\n * @slot description - Custom HTML description content.\n *\n * @example Basic radio group\n * ```html\n * <nys-radiogroup label=\"Select borough\" required>\n * <nys-radiobutton name=\"borough\" value=\"bronx\" label=\"The Bronx\"></nys-radiobutton>\n * <nys-radiobutton name=\"borough\" value=\"brooklyn\" label=\"Brooklyn\"></nys-radiobutton>\n * <nys-radiobutton name=\"borough\" value=\"manhattan\" label=\"Manhattan\"></nys-radiobutton>\n * </nys-radiogroup>\n * ```\n */\n\nexport class NysRadiogroup extends LitElement {\n static styles = unsafeCSS(styles);\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n /** Unique identifier. Auto-generated if not provided. */\n @property({ type: String, reflect: true }) id = \"\";\n\n /** Name for form submission. Auto-populated from child radiobuttons. */\n @property({ type: String, reflect: true }) name = \"\";\n\n /** Requires a selection before form submission. */\n @property({ type: Boolean, reflect: true }) required = false;\n\n /** Shows \"Optional\" flag. */\n @property({ type: Boolean, reflect: true }) optional = false;\n\n /** Shows error message when true. */\n @property({ type: Boolean, reflect: true }) showError = false;\n\n /** Error message text. Shown only when `showError` is true. */\n @property({ type: String }) errorMessage = \"\";\n\n /** Visible label text for the group. */\n @property({ type: String }) label = \"\";\n\n /** Helper text below label. Use slot for custom HTML. */\n @property({ type: String }) description = \"\";\n\n /** Renders all radiobuttons as tiles with larger clickable area. */\n @property({ type: Boolean, reflect: true }) tile = false;\n\n /** Tooltip text shown on hover/focus of info icon. */\n @property({ type: String }) tooltip = \"\";\n\n /** Adjusts colors for dark backgrounds. Applied to all children. */\n @property({ type: Boolean, reflect: true }) inverted = false;\n\n /** Form `id` to associate with. Applied to all children. */\n @property({ type: String, reflect: true }) form: string | null = null;\n\n /**\n * Radio size for all children: `sm` (24px) or `md` (32px, default).\n * @default \"md\"\n */\n @property({ type: String, reflect: true }) size: \"sm\" | \"md\" = \"md\";\n\n @state() private selectedValue: string | null = null;\n @state() private _slottedDescriptionText = \"\";\n\n private _internals: ElementInternals;\n\n /**\n * Lifecycle methods\n * --------------------------------------------------------------------------\n */\n\n static formAssociated = true; // allows use of elementInternals' API\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n // Generate a unique ID if one is not provided\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-radiogroup-${Date.now()}-${radiogroupIdCounter++}`;\n }\n this.addEventListener(\"nys-change\", this._handleRadioButtonChange);\n this.addEventListener(\"invalid\", this._handleInvalid);\n this.addEventListener(\"nys-error\", this._handleChildError);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"nys-change\", this._handleRadioButtonChange);\n this.removeEventListener(\"invalid\", this._handleInvalid);\n }\n\n async firstUpdated() {\n await this.updateComplete;\n this._initializeCheckedRadioValue();\n this._setValue(); // This ensures our element always participates in the form\n this._setRadioButtonRequire();\n this._updateRadioButtonsSize();\n this._updateRadioButtonsTile();\n this._updateRadioButtonsShowError();\n this._getSlotDescriptionForAria();\n\n this._initializeChildAttributes();\n this._updateGroupTabIndex();\n }\n\n updated(changedProperties: Map<string | symbol, unknown>) {\n if (\n changedProperties.has(\"required\") ||\n changedProperties.has(\"selectedValue\")\n ) {\n this._manageRequire();\n }\n if (changedProperties.has(\"size\")) {\n this._updateRadioButtonsSize();\n }\n if (changedProperties.has(\"tile\")) {\n this._updateRadioButtonsTile();\n }\n if (changedProperties.has(\"inverted\")) {\n this._updateRadioButtonsInvert();\n }\n if (changedProperties.has(\"showError\")) {\n this._updateRadioButtonsShowError();\n }\n if (changedProperties.has(\"form\")) {\n this._updateRadioButtonsForm();\n }\n }\n\n /**\n * Form Integration\n * --------------------------------------------------------------------------\n */\n\n private _setValue() {\n this._internals.setFormValue(this.selectedValue);\n }\n\n // Updates the \"require\" attribute of the first radiobutton underneath a radiogroup.\n // This will make sure there's a requirement for all radiobutton under the same name/group\n private _setRadioButtonRequire() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton, index) => {\n if (this.required && index === 0) {\n radioButton.setAttribute(\"required\", \"required\");\n }\n });\n }\n\n private async _manageRequire() {\n const message = this.errorMessage || \"Please select an option.\";\n\n const radioButtons = Array.from(this.querySelectorAll(\"nys-radiobutton\"));\n const firstRadio = radioButtons[0] as HTMLElement;\n\n if (firstRadio) {\n if (this.required && !this.selectedValue) {\n this._internals.setValidity(\n { valueMissing: true },\n message,\n firstRadio, // pass the custom element, not shadow input\n );\n } else {\n this.showError = false;\n this._internals.setValidity({}, \"\", firstRadio);\n }\n }\n }\n\n checkValidity() {\n const radioButtons = Array.from(this.querySelectorAll(\"nys-radiobutton\"));\n const valid =\n !this.required ||\n radioButtons.some((radio) => (radio as NysRadiobutton).checked);\n return valid;\n }\n\n // Need to account for if radiogroup already have a radiobutton checked at initialization\n private _initializeCheckedRadioValue() {\n const checkedRadio = this.querySelector(\"nys-radiobutton[checked]\");\n if (checkedRadio) {\n this.selectedValue = checkedRadio.getAttribute(\"value\");\n this._internals.setFormValue(this.selectedValue);\n }\n }\n\n // Core Keyboard & Click Logic\n private _getAllRadios() {\n return Array.from(\n this.querySelectorAll(\"nys-radiobutton\"),\n ) as NysRadiobutton[];\n }\n\n // Arrow / Space / Enter navigation at group level\n private async _handleKeyDown(event: KeyboardEvent) {\n const keys = [\"ArrowUp\", \"ArrowDown\", \" \", \"Enter\"];\n\n if (!keys.includes(event.key)) return;\n event.preventDefault();\n\n const radioBtns = this._getAllRadios().filter((radio) => !radio.disabled);\n\n const focusedRadio = radioBtns.find((radio) => radio.matches(\":focus\"));\n const currentRadio =\n focusedRadio || radioBtns.find((radio) => radio.checked) || radioBtns[0]; // fallback is checked radio or first radio\n\n let increment = 0;\n if ([\"ArrowUp\", \"ArrowLeft\"].includes(event.key)) {\n increment = -1;\n } else if ([\"ArrowDown\", \"ArrowRight\"].includes(event.key)) {\n increment = 1;\n }\n\n let index = radioBtns.indexOf(currentRadio) + increment;\n\n // Handles the wrap around ends if user is at first or last radiobutton\n if (index < 0) {\n index = radioBtns.length - 1;\n }\n if (index >= radioBtns.length) {\n index = 0;\n }\n\n const target = radioBtns[index];\n const input = await target.getInputElement();\n input?.click();\n\n await this.updateComplete;\n this._updateGroupTabIndex();\n target.focus();\n }\n\n private _updateGroupTabIndex() {\n const radios = this._getAllRadios();\n\n // Pick active: checked first, otherwise first enabled\n const active =\n radios.find((radio) => radio.checked && !radio.disabled) ||\n radios.find((radio) => !radio.disabled);\n\n radios.forEach((radio) => {\n radio.setAttribute(\"aria-checked\", String(radio.checked));\n // Only one radiobutton can be focusable at all times.\n // Due to this, we calculate logic to determine an active radiobutton and call all other as tabindex=\"-1\"\n radio.tabIndex = radio === active && !radio.disabled ? 0 : -1;\n });\n }\n\n // This callback is automatically called when the parent form is reset.\n public formResetCallback() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n (radioButton as NysRadiobutton).formResetUpdate();\n });\n\n this.selectedValue = null;\n\n this._internals.setFormValue(null);\n\n // Reset validation UI\n this.showError = false;\n this.errorMessage = \"\";\n this._internals.setValidity({});\n\n // Re-render UI\n this.requestUpdate();\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n // Apply ARIA & initial tabindex to each child radio\n private _initializeChildAttributes() {\n const radios = this._getAllRadios();\n radios.forEach((radio) => {\n radio.setAttribute(\"role\", \"radio\");\n radio.setAttribute(\"aria-checked\", String(radio.checked));\n radio.setAttribute(\"aria-required\", String(radio.required));\n radio.setAttribute(\"aria-disabled\", String(radio.disabled));\n radio.setAttribute(\"tabindex\", \"-1\");\n });\n }\n\n // Updates the size of each radiobutton underneath a radiogroup to ensure size standardization\n private _updateRadioButtonsSize() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n radioButton.setAttribute(\"size\", this.size);\n });\n }\n\n private _updateRadioButtonsTile() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n if (this.tile) {\n radioButton.toggleAttribute(\"tile\", true);\n } else {\n radioButton.removeAttribute(\"tile\");\n }\n });\n }\n\n private _updateRadioButtonsInvert() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n if (this.inverted) {\n radioButton.toggleAttribute(\"inverted\", true);\n } else {\n radioButton.removeAttribute(\"inverted\");\n }\n });\n }\n\n private _updateRadioButtonsShowError() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n if (this.showError) {\n radioButton.setAttribute(\"showError\", \"\");\n } else {\n radioButton.removeAttribute(\"showError\");\n }\n });\n }\n\n private _updateRadioButtonsForm() {\n const radioButtons = this.querySelectorAll(\"nys-radiobutton\");\n radioButtons.forEach((radioButton) => {\n if (this.showError) {\n if (this.form !== null) {\n radioButton.setAttribute(\"form\", this.form);\n } else {\n radioButton.removeAttribute(\"form\");\n }\n } else {\n radioButton.removeAttribute(\"form\");\n }\n });\n }\n\n // Get the slotted text contents so native VO can attempt to announce it within the legend in the fieldset\n private _getSlotDescriptionForAria() {\n const slot = this.shadowRoot?.querySelector(\n 'slot[name=\"description\"]',\n ) as HTMLSlotElement;\n const nodes = slot?.assignedNodes({ flatten: true }) || [];\n\n this._slottedDescriptionText = nodes\n .map((node) => node.textContent?.trim())\n .filter(Boolean)\n .join(\", \");\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n // Keeps radiogroup informed of the name and value of its current selected radiobutton at each change\n private _handleRadioButtonChange(event: Event) {\n const { name, value } = (event as CustomEvent).detail;\n\n this.name = name;\n this.selectedValue = value;\n this._internals.setFormValue(this.selectedValue);\n\n // selecting anything clears group required error\n this._internals.setValidity({});\n this.showError = false;\n\n // Accounts for tabindex & ARIA on every click/space select\n this._updateGroupTabIndex();\n }\n\n private async _handleInvalid(event: Event) {\n event.preventDefault();\n\n // Focus \"other\" text input when customError is set\n if (this._internals.validity.customError) {\n const radios = this._getAllRadios();\n const otherRadio = radios.find((radio) => radio.other && radio.checked);\n\n if (otherRadio) {\n const textInput = otherRadio.shadowRoot?.querySelector(\"nys-textinput\");\n otherRadio.classList.remove(\"focused\");\n\n if (textInput) {\n await (textInput as any).updateComplete;\n (textInput as HTMLElement).focus();\n return;\n }\n }\n }\n\n // Check if the radio group is invalid and set `showError` accordingly\n if (this._internals.validity.valueMissing) {\n this.showError = true;\n this._manageRequire(); // Refresh validation message\n\n const firstRadio = this.querySelector(\n \"nys-radiobutton\",\n ) as NysRadiobutton;\n\n if (firstRadio) {\n // Focus only if this is the first invalid element (top-down approach)\n const form = this._internals.form;\n if (form) {\n const elements = Array.from(form.elements) as Array<\n HTMLElement & { checkValidity?: () => boolean }\n >;\n\n // Find the first element in the form that is invalid\n const firstInvalidElement = elements.find(\n (element) =>\n typeof element.checkValidity === \"function\" &&\n !element.checkValidity(),\n );\n if (firstInvalidElement === this) {\n firstRadio.focus();\n }\n } else {\n // If not part of a form, simply focus.\n firstRadio.focus();\n }\n }\n }\n }\n\n private _handleChildError(event: Event) {\n event.stopPropagation();\n\n const { message, sourceRadio } = (event as CustomEvent).detail;\n if (!sourceRadio) return;\n\n this.showError = true;\n\n this._internals.setValidity(\n { customError: true },\n message || \"Please complete this field.\",\n sourceRadio as HTMLElement,\n );\n }\n\n render() {\n return html`<fieldset\n aria-label=\"${this.label}${this._slottedDescriptionText\n ? ` ${this._slottedDescriptionText}`\n : this.description\n ? ` ${this.description}`\n : \"\"}\"\n role=\"radiogroup\"\n class=\"nys-radiogroup\"\n >\n <nys-label\n for=${this.id + \"--native\"}\n label=${this.label}\n description=${this.description}\n flag=${this.required ? \"required\" : this.optional ? \"optional\" : \"\"}\n tooltip=${this.tooltip}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\">${this.description}</slot>\n </nys-label>\n <div class=\"nys-radiogroup__content\" @keydown=${this._handleKeyDown}>\n <slot></slot>\n </div>\n <nys-errormessage\n ?showError=${this.showError}\n errorMessage=${this._internals.validationMessage || this.errorMessage}\n .showDivider=${!this.tile}\n ></nys-errormessage>\n </fieldset>`;\n }\n}\n\nif (!customElements.get(\"nys-radiogroup\")) {\n customElements.define(\"nys-radiogroup\", NysRadiogroup);\n}\n","import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property, state } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\nimport \"./nys-radiogroup\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-radiobutton.scss?inline\";\n\nlet radiobuttonIdCounter = 0;\n\n/**\n * A radio button for single selection within a `nys-radiogroup`. Only one radio with the same `name` can be selected.\n *\n * Use within `nys-radiogroup` for 2-6 mutually exclusive options. For 7+ options, use `nys-select`.\n * For multiple selections, use `nys-checkbox`.\n *\n * @summary Radio button for single selection from mutually exclusive options.\n * @element nys-radiobutton\n *\n * @slot description - Custom HTML description content.\n *\n * @fires nys-change - Fired when selection changes. Detail: `{id, checked, name, value}`.\n * @fires nys-focus - Fired when radio gains focus.\n * @fires nys-blur - Fired when radio loses focus.\n * @fires nys-other-input - Fired when \"other\" text input value changes. Detail: `{id, name, value}`.\n *\n * @example Radio group\n * ```html\n * <nys-radiogroup label=\"Select borough\" required>\n * <nys-radiobutton name=\"borough\" value=\"bronx\" label=\"The Bronx\"></nys-radiobutton>\n * <nys-radiobutton name=\"borough\" value=\"brooklyn\" label=\"Brooklyn\"></nys-radiobutton>\n * </nys-radiogroup>\n * ```\n */\n\nexport class NysRadiobutton extends LitElement {\n static styles = unsafeCSS(styles);\n static shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n /** Whether this radio is selected. Only one per group can be checked. */\n @property({ type: Boolean, reflect: true }) checked = false;\n\n /** Prevents interaction. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n /** Marks group as required. Set on radiogroup, not individual radios. */\n @property({ type: Boolean, reflect: true }) required = false;\n\n /** Visible label text. Required for accessibility. */\n @property({ type: String }) label = \"\";\n\n /** Helper text below label. Use slot for custom HTML. */\n @property({ type: String }) description = \"\";\n\n /** Unique identifier. Auto-generated if not provided. */\n @property({ type: String, reflect: true }) id = \"\";\n\n /** Group name. Radios with same name are mutually exclusive. */\n @property({ type: String, reflect: true }) name = \"\";\n\n /** Value submitted when this radio is selected. */\n @property({ type: String }) value = \"\";\n\n /** Adjusts colors for dark backgrounds. */\n @property({ type: Boolean, reflect: true }) inverted = false;\n\n /** Form `id` to associate with. */\n @property({ type: String, reflect: true }) form: string | null = null;\n\n /**\n * Radio size: `sm` (24px) or `md` (32px, default).\n * @default \"md\"\n */\n @property({ type: String, reflect: true }) size: \"sm\" | \"md\" = \"md\";\n\n /** Renders as tile with larger clickable area. */\n @property({ type: Boolean, reflect: true }) tile = false;\n @property({ type: Boolean, reflect: true }) other = false;\n @property({ type: Boolean }) showOtherError = false;\n\n @state() private isMobile = window.innerWidth < 480;\n\n private _hasUserInteracted = false; // need this flag for \"eager mode\"\n\n static buttonGroup: Record<string, NysRadiobutton> = {};\n\n /**\n * Lifecycle methods\n * --------------------------------------------------------------------------\n */\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-radiobutton-${Date.now()}-${radiobuttonIdCounter++}`;\n }\n\n // If this button is initially checked, set it as the current button in its group\n if (this.checked) {\n if (NysRadiobutton.buttonGroup[this.name]) {\n NysRadiobutton.buttonGroup[this.name].checked = false;\n NysRadiobutton.buttonGroup[this.name].requestUpdate();\n }\n NysRadiobutton.buttonGroup[this.name] = this;\n }\n\n this.addEventListener(\"focus\", this._handleFocus);\n this.addEventListener(\"blur\", this._handleBlur);\n this.addEventListener(\"click\", this._handleChange);\n window.addEventListener(\"resize\", this._handleResize);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n\n this.removeEventListener(\"focus\", this._handleFocus);\n this.removeEventListener(\"blur\", this._handleBlur);\n window.removeEventListener(\"resize\", this._handleResize);\n }\n\n updated(changedProperties: Map<string | number | symbol, unknown>) {\n // When \"checked\" changes, update the internals.\n if (changedProperties.has(\"checked\")) {\n const wasChecked = changedProperties.get(\"checked\") as\n | boolean\n | undefined;\n\n // If this radio was unchecked, clear \"other\" error state\n if (wasChecked && !this.checked) {\n this._clearOtherState();\n }\n\n // Ensure only one radiobutton per group is checked.\n if (this.checked && NysRadiobutton.buttonGroup[this.name] !== this) {\n if (NysRadiobutton.buttonGroup[this.name]) {\n NysRadiobutton.buttonGroup[this.name].checked = false;\n NysRadiobutton.buttonGroup[this.name].requestUpdate();\n }\n NysRadiobutton.buttonGroup[this.name] = this;\n }\n }\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n public async getInputElement(): Promise<HTMLInputElement | null> {\n await this.updateComplete; // Wait for the component to finish rendering\n return this.shadowRoot?.querySelector(\"input\") || null;\n }\n\n // This callback is automatically called when the parent form is reset.\n public formResetUpdate() {\n this.checked = false;\n this._clearOtherState();\n\n if (NysRadiobutton.buttonGroup[this.name] === this) {\n delete NysRadiobutton.buttonGroup[this.name];\n }\n\n // Re-render UI\n this.requestUpdate();\n }\n\n private _handleResize = () => {\n this.isMobile = window.innerWidth < 480;\n };\n\n private _clearOtherState() {\n if (!this.other) return;\n\n this.showOtherError = false;\n this._hasUserInteracted = false;\n\n // Optional: clear error at the group level\n this.dispatchEvent(\n new CustomEvent(\"nys-error-clear\", {\n detail: {\n id: this.id,\n name: this.name,\n type: \"other\",\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n private _emitChangeEvent() {\n this.dispatchEvent(\n new CustomEvent(\"nys-change\", {\n detail: {\n id: this.id,\n checked: this.checked,\n name: this.name,\n value: this.value,\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _emitOtherInputEvent() {\n this.dispatchEvent(\n new CustomEvent(\"nys-other-input\", {\n detail: {\n id: this.id,\n name: this.name,\n value: this.value,\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n // Handle radiobutton change event & un-selection of other radio options in group\n private async _handleChange() {\n this.showOtherError = false;\n\n if (!this.checked && !this.disabled) {\n if (NysRadiobutton.buttonGroup[this.name]) {\n NysRadiobutton.buttonGroup[this.name].checked = false;\n NysRadiobutton.buttonGroup[this.name].requestUpdate();\n }\n NysRadiobutton.buttonGroup[this.name] = this;\n\n this.checked = true;\n this._validateOtherAndEmitError();\n this._emitChangeEvent();\n }\n }\n\n // Handle focus event\n private _handleFocus() {\n this.dispatchEvent(new Event(\"nys-focus\"));\n }\n\n // Handle blur event\n private _handleBlur() {\n this.dispatchEvent(new Event(\"nys-blur\"));\n\n setTimeout(() => {\n // Only validate if we're blurring away from the component entirely\n // and this is an \"other\" radio that's checked\n if (this.other && this.checked) {\n this._hasUserInteracted = true;\n this._validateOtherAndEmitError();\n }\n }, 50);\n }\n\n private _callInputHandling() {\n if (this.disabled) return;\n\n // Find the hidden input and trigger a click to toggle selection\n const input = this.shadowRoot?.querySelector(\n 'input[type=\"radio\"]',\n ) as HTMLInputElement;\n\n if (input) {\n input.focus();\n input.click();\n }\n }\n\n private _handleTextInput(event: Event) {\n const input = event.target as HTMLInputElement;\n let newValue = input.value;\n this.value = newValue;\n\n if (this._hasUserInteracted) {\n this._validateOtherAndEmitError();\n }\n\n this._emitOtherInputEvent();\n }\n\n private _handleTextInputBlur() {\n this._hasUserInteracted = true;\n this._validateOtherAndEmitError();\n }\n\n private _validateOtherAndEmitError() {\n if (!this.other) return;\n\n if (!this.checked || !this._hasUserInteracted) {\n this.showOtherError = false;\n return;\n }\n\n const isInvalid = this.value.trim() === \"\";\n this.showOtherError = isInvalid;\n\n if (isInvalid) {\n this.dispatchEvent(\n new CustomEvent(\"nys-error\", {\n detail: {\n id: this.id,\n name: this.name,\n type: \"other\",\n message: \"Please enter a value for this option.\",\n sourceRadio: this,\n },\n bubbles: true,\n composed: true,\n }),\n );\n }\n }\n\n private _handleOtherKeydown(e: KeyboardEvent) {\n if (e.key == \"Space\" || e.key === \" \") {\n e.stopPropagation();\n }\n }\n\n render() {\n return html`\n <input\n type=\"radio\"\n name=\"${ifDefined(this.name ? this.name : undefined)}\"\n .checked=${this.checked}\n ?disabled=${this.disabled}\n .value=${this.value}\n ?required=\"${this.required}\"\n form=${ifDefined(this.form || undefined)}\n @change=\"${this._handleChange}\"\n aria-hidden=\"true\"\n hidden\n class=\"sr-only\"\n />\n <div\n class=\"nys-radiobutton\"\n @click=\"${this._callInputHandling}\"\n aria-label=${this.label || (this.other ?? \"Other\")}\n >\n <div class=\"nys-radiobutton__main-container\">\n <span class=\"nys-radiobutton__radio\"></span>\n ${(this.label || this.other) &&\n html`<nys-label\n label=\"${this.label || (this.other ? \"Other\" : \"\")}\"\n description=${ifDefined(this.description || undefined)}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\"\n >${this.description}</slot\n >\n </nys-label> `}\n </div>\n <div class=\"nys-radiobutton__other-container\">\n ${this.other && this.checked\n ? html`\n <nys-textinput\n .value=${this.value}\n id=${\"radiobutton-other-\" + this.id}\n @nys-input=${this._handleTextInput}\n @nys-blur=${this._handleTextInputBlur}\n @keydown=${this._handleOtherKeydown}\n @nys-focus=${() => this.classList.remove(\"focused\")}\n ariaLabel=\"Other\"\n aria-invalid=${this.showOtherError ? \"true\" : \"false\"}\n width=${this.isMobile ? \"full\" : \"md\"}\n ></nys-textinput>\n `\n : \"\"}\n </div>\n </div>\n `;\n }\n}\n\nif (!customElements.get(\"nys-radiobutton\")) {\n customElements.define(\"nys-radiobutton\", NysRadiobutton);\n}\n"],"names":["radiogroupIdCounter","_NysRadiogroup","LitElement","changedProperties","radioButton","index","message","firstRadio","radioButtons","radio","checkedRadio","event","radioBtns","currentRadio","increment","target","radios","active","nodes","node","name","value","otherRadio","textInput","form","element","sourceRadio","html","unsafeCSS","styles","NysRadiogroup","__decorateClass","property","state","radiobuttonIdCounter","_NysRadiobutton","_a","input","newValue","isInvalid","e","ifDefined","NysRadiobutton"],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
/**
|
|
3
|
+
* A container for grouping `nys-radiobutton` elements as a single form control with enforced single selection.
|
|
4
|
+
* Handles keyboard navigation (arrow keys), validation, required constraints, and form integration.
|
|
5
|
+
*
|
|
6
|
+
* Use to let users select exactly one option from 2-6 choices. Apply `tile`, `size`, and `inverted` to the group
|
|
7
|
+
* and all children inherit these styles automatically. For 7+ options, use `nys-select`.
|
|
8
|
+
*
|
|
9
|
+
* @summary Container for grouping radio buttons as a single form control.
|
|
10
|
+
* @element nys-radiogroup
|
|
11
|
+
*
|
|
12
|
+
* @slot - Default slot for `nys-radiobutton` elements.
|
|
13
|
+
* @slot description - Custom HTML description content.
|
|
14
|
+
*
|
|
15
|
+
* @example Basic radio group
|
|
16
|
+
* ```html
|
|
17
|
+
* <nys-radiogroup label="Select borough" required>
|
|
18
|
+
* <nys-radiobutton name="borough" value="bronx" label="The Bronx"></nys-radiobutton>
|
|
19
|
+
* <nys-radiobutton name="borough" value="brooklyn" label="Brooklyn"></nys-radiobutton>
|
|
20
|
+
* <nys-radiobutton name="borough" value="manhattan" label="Manhattan"></nys-radiobutton>
|
|
21
|
+
* </nys-radiogroup>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare class NysRadiogroup extends LitElement {
|
|
25
|
+
static styles: import("lit").CSSResult;
|
|
26
|
+
static shadowRootOptions: {
|
|
27
|
+
delegatesFocus: boolean;
|
|
28
|
+
clonable?: boolean;
|
|
29
|
+
customElementRegistry?: CustomElementRegistry;
|
|
30
|
+
mode: ShadowRootMode;
|
|
31
|
+
serializable?: boolean;
|
|
32
|
+
slotAssignment?: SlotAssignmentMode;
|
|
33
|
+
};
|
|
34
|
+
/** Unique identifier. Auto-generated if not provided. */
|
|
35
|
+
id: string;
|
|
36
|
+
/** Name for form submission. Auto-populated from child radiobuttons. */
|
|
37
|
+
name: string;
|
|
38
|
+
/** Requires a selection before form submission. */
|
|
39
|
+
required: boolean;
|
|
40
|
+
/** Shows "Optional" flag. */
|
|
41
|
+
optional: boolean;
|
|
42
|
+
/** Shows error message when true. */
|
|
43
|
+
showError: boolean;
|
|
44
|
+
/** Error message text. Shown only when `showError` is true. */
|
|
45
|
+
errorMessage: string;
|
|
46
|
+
/** Visible label text for the group. */
|
|
47
|
+
label: string;
|
|
48
|
+
/** Helper text below label. Use slot for custom HTML. */
|
|
49
|
+
description: string;
|
|
50
|
+
/** Renders all radiobuttons as tiles with larger clickable area. */
|
|
51
|
+
tile: boolean;
|
|
52
|
+
/** Tooltip text shown on hover/focus of info icon. */
|
|
53
|
+
tooltip: string;
|
|
54
|
+
/** Adjusts colors for dark backgrounds. Applied to all children. */
|
|
55
|
+
inverted: boolean;
|
|
56
|
+
/** Form `id` to associate with. Applied to all children. */
|
|
57
|
+
form: string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Radio size for all children: `sm` (24px) or `md` (32px, default).
|
|
60
|
+
* @default "md"
|
|
61
|
+
*/
|
|
62
|
+
size: "sm" | "md";
|
|
63
|
+
private selectedValue;
|
|
64
|
+
private _slottedDescriptionText;
|
|
65
|
+
private _internals;
|
|
66
|
+
/**
|
|
67
|
+
* Lifecycle methods
|
|
68
|
+
* --------------------------------------------------------------------------
|
|
69
|
+
*/
|
|
70
|
+
static formAssociated: boolean;
|
|
71
|
+
constructor();
|
|
72
|
+
connectedCallback(): void;
|
|
73
|
+
disconnectedCallback(): void;
|
|
74
|
+
firstUpdated(): Promise<void>;
|
|
75
|
+
updated(changedProperties: Map<string | symbol, unknown>): void;
|
|
76
|
+
/**
|
|
77
|
+
* Form Integration
|
|
78
|
+
* --------------------------------------------------------------------------
|
|
79
|
+
*/
|
|
80
|
+
private _setValue;
|
|
81
|
+
private _setRadioButtonRequire;
|
|
82
|
+
private _manageRequire;
|
|
83
|
+
checkValidity(): boolean;
|
|
84
|
+
private _initializeCheckedRadioValue;
|
|
85
|
+
private _getAllRadios;
|
|
86
|
+
private _handleKeyDown;
|
|
87
|
+
private _updateGroupTabIndex;
|
|
88
|
+
formResetCallback(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Functions
|
|
91
|
+
* --------------------------------------------------------------------------
|
|
92
|
+
*/
|
|
93
|
+
private _initializeChildAttributes;
|
|
94
|
+
private _updateRadioButtonsSize;
|
|
95
|
+
private _updateRadioButtonsTile;
|
|
96
|
+
private _updateRadioButtonsInvert;
|
|
97
|
+
private _updateRadioButtonsShowError;
|
|
98
|
+
private _updateRadioButtonsForm;
|
|
99
|
+
private _getSlotDescriptionForAria;
|
|
100
|
+
/**
|
|
101
|
+
* Event Handlers
|
|
102
|
+
* --------------------------------------------------------------------------
|
|
103
|
+
*/
|
|
104
|
+
private _handleRadioButtonChange;
|
|
105
|
+
private _handleInvalid;
|
|
106
|
+
private _handleChildError;
|
|
107
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
108
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nysds/nys-radiobutton",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "The Radiobutton component from the NYS Design System.",
|
|
5
5
|
"module": "dist/nys-radiobutton.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"lit-analyze": "lit-analyzer '**/*.ts'"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@nysds/nys-label": "^1.
|
|
27
|
-
"@nysds/nys-errormessage": "^1.
|
|
26
|
+
"@nysds/nys-label": "^1.15.0",
|
|
27
|
+
"@nysds/nys-errormessage": "^1.15.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"lit": "^3.3.1",
|
|
31
31
|
"typescript": "^5.9.3",
|
|
32
|
-
"vite": "^7.1
|
|
32
|
+
"vite": "^7.3.1"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [
|
|
35
35
|
"new-york-state",
|