@justeattakeaway/pie-radio 0.2.2 → 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/custom-elements.json +29 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js +84 -66
- package/dist/react.d.ts +13 -4
- package/dist/react.js +6 -3
- package/package.json +1 -1
- package/src/index.ts +57 -21
- package/src/radio.scss +144 -0
- package/src/react.ts +9 -3
package/custom-elements.json
CHANGED
|
@@ -41,6 +41,15 @@
|
|
|
41
41
|
"description": "",
|
|
42
42
|
"name": "PieRadio",
|
|
43
43
|
"members": [
|
|
44
|
+
{
|
|
45
|
+
"kind": "field",
|
|
46
|
+
"name": "_disabledByParent",
|
|
47
|
+
"type": {
|
|
48
|
+
"text": "boolean"
|
|
49
|
+
},
|
|
50
|
+
"privacy": "private",
|
|
51
|
+
"default": "false"
|
|
52
|
+
},
|
|
44
53
|
{
|
|
45
54
|
"kind": "field",
|
|
46
55
|
"name": "checked",
|
|
@@ -89,21 +98,29 @@
|
|
|
89
98
|
},
|
|
90
99
|
{
|
|
91
100
|
"kind": "field",
|
|
92
|
-
"name": "
|
|
101
|
+
"name": "_radio",
|
|
93
102
|
"type": {
|
|
94
103
|
"text": "HTMLInputElement"
|
|
95
104
|
},
|
|
96
105
|
"privacy": "private"
|
|
97
106
|
},
|
|
107
|
+
{
|
|
108
|
+
"kind": "field",
|
|
109
|
+
"name": "_abortController",
|
|
110
|
+
"type": {
|
|
111
|
+
"text": "AbortController"
|
|
112
|
+
},
|
|
113
|
+
"privacy": "private"
|
|
114
|
+
},
|
|
98
115
|
{
|
|
99
116
|
"kind": "method",
|
|
100
|
-
"name": "
|
|
117
|
+
"name": "_handleFormAssociation",
|
|
101
118
|
"privacy": "private",
|
|
102
119
|
"description": "Ensures that the form value is in sync with the component."
|
|
103
120
|
},
|
|
104
121
|
{
|
|
105
122
|
"kind": "method",
|
|
106
|
-
"name": "
|
|
123
|
+
"name": "_handleChange",
|
|
107
124
|
"privacy": "private",
|
|
108
125
|
"parameters": [
|
|
109
126
|
{
|
|
@@ -133,6 +150,15 @@
|
|
|
133
150
|
"description": "Called when the form that contains this component is reset.\nIf the current checked state is different to the default checked state,\nthe checked state is reset to the default checked state and a `change` event is emitted."
|
|
134
151
|
}
|
|
135
152
|
],
|
|
153
|
+
"events": [
|
|
154
|
+
{
|
|
155
|
+
"type": {
|
|
156
|
+
"text": "CustomEvent"
|
|
157
|
+
},
|
|
158
|
+
"description": "when the radio state is changed.",
|
|
159
|
+
"name": "change"
|
|
160
|
+
}
|
|
161
|
+
],
|
|
136
162
|
"attributes": [
|
|
137
163
|
{
|
|
138
164
|
"name": "checked",
|
package/dist/index.d.ts
CHANGED
|
@@ -12,24 +12,29 @@ export declare const defaultProps: DefaultProps;
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @tagname pie-radio
|
|
15
|
+
* @event {CustomEvent} change - when the radio state is changed.
|
|
15
16
|
*/
|
|
16
17
|
export declare class PieRadio extends PieRadio_base implements RadioProps {
|
|
18
|
+
private _disabledByParent;
|
|
17
19
|
checked: boolean;
|
|
18
20
|
defaultChecked: boolean;
|
|
19
21
|
disabled: boolean;
|
|
20
22
|
name: RadioProps['name'];
|
|
21
23
|
required: boolean;
|
|
22
24
|
value: RadioProps['value'];
|
|
23
|
-
private
|
|
25
|
+
private _radio;
|
|
26
|
+
private _abortController;
|
|
27
|
+
connectedCallback(): void;
|
|
28
|
+
disconnectedCallback(): void;
|
|
24
29
|
/**
|
|
25
30
|
* Ensures that the form value is in sync with the component.
|
|
26
31
|
*/
|
|
27
|
-
private
|
|
32
|
+
private _handleFormAssociation;
|
|
28
33
|
/**
|
|
29
34
|
* Captures the native change event and wraps it in a custom event.
|
|
30
35
|
* @param {Event} event - This should be the change event that was listened for on an input element with `type="radio"`.
|
|
31
36
|
*/
|
|
32
|
-
private
|
|
37
|
+
private _handleChange;
|
|
33
38
|
/**
|
|
34
39
|
* (Read-only) returns a ValidityState with the validity states that this element is in.
|
|
35
40
|
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity
|
package/dist/index.js
CHANGED
|
@@ -1,45 +1,56 @@
|
|
|
1
|
-
import { LitElement as
|
|
2
|
-
import { property as
|
|
3
|
-
import { ifDefined as
|
|
4
|
-
import { live as
|
|
5
|
-
import {
|
|
6
|
-
|
|
1
|
+
import { LitElement as v, html as u, unsafeCSS as f } from "lit";
|
|
2
|
+
import { state as m, property as i, query as k } from "lit/decorators.js";
|
|
3
|
+
import { ifDefined as g } from "lit/directives/if-defined.js";
|
|
4
|
+
import { live as y } from "lit/directives/live.js";
|
|
5
|
+
import { classMap as C } from "lit/directives/class-map.js";
|
|
6
|
+
import { FormControlMixin as _, RtlMixin as z, wrapNativeEvent as x, requiredProperty as w, defineCustomElement as E } from "@justeattakeaway/pie-webc-core";
|
|
7
|
+
const l = {
|
|
7
8
|
checked: !1,
|
|
8
9
|
defaultChecked: !1,
|
|
9
10
|
disabled: !1,
|
|
10
11
|
required: !1
|
|
11
|
-
},
|
|
12
|
-
var
|
|
13
|
-
for (var
|
|
14
|
-
(
|
|
15
|
-
return
|
|
12
|
+
}, q = '*,*:after,*:before{box-sizing:inherit}.c-radio{--radio-dot-bg-color: var(--dt-color-content-interactive-primary);--radio-bg-color: transparent;--radio-bg-color--checked: var(--dt-color-interactive-brand);--radio-border-color: var(--dt-color-interactive-form);--radio-font-size: p.font-size(--dt-font-body-l-size);--radio-font-weight: var(--dt-font-weight-regular);--radio-text-color: var(--dt-color-content-default);--radio-size: 24px;--radio-dot-size: 8px;--radio-cursor: pointer;--radio-motion-easing: var(--dt-motion-easing-persistent-functional);--radio-border-width: 1px;display:flex;align-items:center;gap:var(--dt-spacing-b);cursor:var(--radio-cursor);font-size:var(--radio-font-size);font-weight:var(--radio-font-weight);color:var(--radio-text-color)}.c-radio.c-radio--disabled{--radio-cursor: not-allowed}.c-radio input[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:block;position:relative;inline-size:var(--radio-size);block-size:var(--radio-size);border:var(--radio-border-width) solid var(--radio-border-color);border-radius:50%;margin:0;cursor:var(--radio-cursor);background-color:transparent;transition:background-color var(--dt-motion-timing-100) var(--radio-motion-easing);flex-shrink:0}.c-radio input[type=radio]:focus{box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}.c-radio input[type=radio]:before{--circle-size: calc(var(--radio-border-width) * -1);content:"";display:block;inset:var(--circle-size);border-radius:inherit;background-color:var(--radio-bg-color--checked);position:absolute;transform:scale(0)}@media (prefers-reduced-motion: no-preference){.c-radio input[type=radio]:not(:disabled):before{transition:all var(--dt-motion-timing-100) var(--radio-motion-easing)}}.c-radio input[type=radio]:after{content:"";position:absolute;top:50%;left:50%;width:var(--radio-dot-size);height:var(--radio-dot-size);background-color:var(--radio-dot-bg-color);border-radius:50%;transform:translate(-50%,-50%) scale(0)}.c-radio input[type=radio]:checked:after{transform:translate(-50%,-50%) scale(1)}.c-radio input[type=radio]:checked:before{transform:scale(1)}@media (prefers-reduced-motion: no-preference){.c-radio input[type=radio]:not(:disabled):after{transition:all var(--dt-motion-timing-100) var(--radio-motion-easing)}}@media (prefers-reduced-motion: no-preference){.c-radio input[type=radio]:not(:disabled):checked:after{transition:all var(--dt-motion-timing-150) var(--radio-motion-easing)}}.c-radio input[type=radio]:disabled{background-color:var(--dt-color-disabled-01);border-color:var(--dt-color-border-default)}.c-radio input[type=radio]:checked:disabled{--radio-dot-bg-color: var(--dt-color-content-disabled);--radio-bg-color--checked: var(--dt-color-disabled-01)}.c-radio input[type=radio]:hover:not(:checked,:disabled){background-color:hsl(var(--dt-color-black-h),var(--dt-color-black-s),var(--dt-color-black-l),var(--dt-color-hover-01))}.c-radio input[type=radio]:active:not(:checked,:disabled){background-color:hsl(var(--dt-color-black-h),var(--dt-color-black-s),var(--dt-color-black-l),var(--dt-color-active-01))}.c-radio input[type=radio]:hover:checked:not(:disabled):before{background-color:hsl(var(--dt-color-interactive-brand-h),var(--dt-color-interactive-brand-s),calc(var(--dt-color-interactive-brand-l) - var(--dt-color-hover-01)));border-color:hsl(var(--dt-color-interactive-brand-h),var(--dt-color-interactive-brand-s),calc(var(--dt-color-interactive-brand-l) - var(--dt-color-hover-01)))}.c-radio input[type=radio]:active:checked:not(:disabled):before{background-color:hsl(var(--dt-color-interactive-brand-h),var(--dt-color-interactive-brand-s),calc(var(--dt-color-interactive-brand-l) - var(--dt-color-active-01)));border-color:hsl(var(--dt-color-interactive-brand-h),var(--dt-color-interactive-brand-s),calc(var(--dt-color-interactive-brand-l) - var(--dt-color-active-01)))}';
|
|
13
|
+
var B = Object.defineProperty, a = (p, r, o, c) => {
|
|
14
|
+
for (var t = void 0, d = p.length - 1, n; d >= 0; d--)
|
|
15
|
+
(n = p[d]) && (t = n(r, o, t) || t);
|
|
16
|
+
return t && B(r, o, t), t;
|
|
16
17
|
};
|
|
17
|
-
const
|
|
18
|
+
const h = "pie-radio", s = class s extends _(z(v)) {
|
|
18
19
|
constructor() {
|
|
19
|
-
super(...arguments), this.checked =
|
|
20
|
+
super(...arguments), this._disabledByParent = !1, this.checked = l.checked, this.defaultChecked = l.defaultChecked, this.disabled = l.disabled, this.required = l.required;
|
|
21
|
+
}
|
|
22
|
+
connectedCallback() {
|
|
23
|
+
super.connectedCallback(), this._abortController = new AbortController();
|
|
24
|
+
const { signal: r } = this._abortController;
|
|
25
|
+
this.addEventListener("pie-radio-group-disabled", (o) => {
|
|
26
|
+
this._disabledByParent = o.detail.disabled;
|
|
27
|
+
}, { signal: r });
|
|
28
|
+
}
|
|
29
|
+
disconnectedCallback() {
|
|
30
|
+
super.disconnectedCallback(), this._abortController.abort();
|
|
20
31
|
}
|
|
21
32
|
/**
|
|
22
33
|
* Ensures that the form value is in sync with the component.
|
|
23
34
|
*/
|
|
24
|
-
|
|
35
|
+
_handleFormAssociation() {
|
|
25
36
|
this.form && this.name && this._internals.setFormValue(this.checked ? this.value : null);
|
|
26
37
|
}
|
|
27
38
|
/**
|
|
28
39
|
* Captures the native change event and wraps it in a custom event.
|
|
29
40
|
* @param {Event} event - This should be the change event that was listened for on an input element with `type="radio"`.
|
|
30
41
|
*/
|
|
31
|
-
|
|
32
|
-
const { checked: o } =
|
|
42
|
+
_handleChange(r) {
|
|
43
|
+
const { checked: o } = r == null ? void 0 : r.currentTarget;
|
|
33
44
|
this.checked = o;
|
|
34
|
-
const
|
|
35
|
-
this.dispatchEvent(
|
|
45
|
+
const c = x(r);
|
|
46
|
+
this.dispatchEvent(c), this._handleFormAssociation();
|
|
36
47
|
}
|
|
37
48
|
/**
|
|
38
49
|
* (Read-only) returns a ValidityState with the validity states that this element is in.
|
|
39
50
|
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity
|
|
40
51
|
*/
|
|
41
52
|
get validity() {
|
|
42
|
-
return this.
|
|
53
|
+
return this._radio.validity;
|
|
43
54
|
}
|
|
44
55
|
/**
|
|
45
56
|
* Called when the form that contains this component is reset.
|
|
@@ -50,62 +61,69 @@ const p = "pie-radio", l = class l extends v(C(u)) {
|
|
|
50
61
|
if (this.checked === this.defaultChecked)
|
|
51
62
|
return;
|
|
52
63
|
this.checked = this.defaultChecked;
|
|
53
|
-
const
|
|
54
|
-
this.dispatchEvent(
|
|
64
|
+
const r = new Event("change", { bubbles: !0, composed: !0 });
|
|
65
|
+
this.dispatchEvent(r), this._handleFormAssociation();
|
|
55
66
|
}
|
|
56
67
|
updated() {
|
|
57
|
-
this.
|
|
68
|
+
this._handleFormAssociation();
|
|
58
69
|
}
|
|
59
70
|
render() {
|
|
60
71
|
const {
|
|
61
|
-
checked:
|
|
72
|
+
checked: r,
|
|
62
73
|
disabled: o,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
_disabledByParent: c,
|
|
75
|
+
name: t,
|
|
76
|
+
required: d,
|
|
77
|
+
value: n
|
|
78
|
+
} = this, b = o || c;
|
|
79
|
+
return u`
|
|
80
|
+
<label class=${C({
|
|
81
|
+
"c-radio": !0,
|
|
82
|
+
"c-radio--disabled": b
|
|
83
|
+
})} for="radioId">
|
|
84
|
+
<input
|
|
85
|
+
type="radio"
|
|
86
|
+
id="radioId"
|
|
87
|
+
data-test-id="pie-radio"
|
|
88
|
+
.checked="${y(r)}"
|
|
89
|
+
.value="${n}"
|
|
90
|
+
name="${g(t)}"
|
|
91
|
+
?disabled="${b}"
|
|
92
|
+
?required="${d}"
|
|
93
|
+
@change="${this._handleChange}">
|
|
79
94
|
<slot></slot>
|
|
80
95
|
</label>`;
|
|
81
96
|
}
|
|
82
97
|
};
|
|
83
|
-
|
|
84
|
-
let
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
],
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
],
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
],
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
],
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
],
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
i(
|
|
105
|
-
|
|
106
|
-
],
|
|
107
|
-
|
|
98
|
+
s.styles = f(q);
|
|
99
|
+
let e = s;
|
|
100
|
+
a([
|
|
101
|
+
m()
|
|
102
|
+
], e.prototype, "_disabledByParent");
|
|
103
|
+
a([
|
|
104
|
+
i({ type: Boolean, reflect: !0 })
|
|
105
|
+
], e.prototype, "checked");
|
|
106
|
+
a([
|
|
107
|
+
i({ type: Boolean, reflect: !0 })
|
|
108
|
+
], e.prototype, "defaultChecked");
|
|
109
|
+
a([
|
|
110
|
+
i({ type: Boolean, reflect: !0 })
|
|
111
|
+
], e.prototype, "disabled");
|
|
112
|
+
a([
|
|
113
|
+
i({ type: String })
|
|
114
|
+
], e.prototype, "name");
|
|
115
|
+
a([
|
|
116
|
+
i({ type: Boolean, reflect: !0 })
|
|
117
|
+
], e.prototype, "required");
|
|
118
|
+
a([
|
|
119
|
+
i({ type: String }),
|
|
120
|
+
w(h)
|
|
121
|
+
], e.prototype, "value");
|
|
122
|
+
a([
|
|
123
|
+
k('input[type="radio"]')
|
|
124
|
+
], e.prototype, "_radio");
|
|
125
|
+
E(h, e);
|
|
108
126
|
export {
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
e as PieRadio,
|
|
128
|
+
l as defaultProps
|
|
111
129
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -11,28 +11,33 @@ export declare type DefaultProps = ComponentDefaultProps<RadioProps, keyof Omit<
|
|
|
11
11
|
|
|
12
12
|
export declare const defaultProps: DefaultProps;
|
|
13
13
|
|
|
14
|
-
export declare const PieRadio: React_2.ForwardRefExoticComponent<RadioProps & React_2.RefAttributes<PieRadio_2> & ReactBaseType>;
|
|
14
|
+
export declare const PieRadio: React_2.ForwardRefExoticComponent<RadioProps & React_2.RefAttributes<PieRadio_2> & PieRadioEvents & ReactBaseType>;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @tagname pie-radio
|
|
18
|
+
* @event {CustomEvent} change - when the radio state is changed.
|
|
18
19
|
*/
|
|
19
20
|
declare class PieRadio_2 extends PieRadio_base implements RadioProps {
|
|
21
|
+
private _disabledByParent;
|
|
20
22
|
checked: boolean;
|
|
21
23
|
defaultChecked: boolean;
|
|
22
24
|
disabled: boolean;
|
|
23
25
|
name: RadioProps['name'];
|
|
24
26
|
required: boolean;
|
|
25
27
|
value: RadioProps['value'];
|
|
26
|
-
private
|
|
28
|
+
private _radio;
|
|
29
|
+
private _abortController;
|
|
30
|
+
connectedCallback(): void;
|
|
31
|
+
disconnectedCallback(): void;
|
|
27
32
|
/**
|
|
28
33
|
* Ensures that the form value is in sync with the component.
|
|
29
34
|
*/
|
|
30
|
-
private
|
|
35
|
+
private _handleFormAssociation;
|
|
31
36
|
/**
|
|
32
37
|
* Captures the native change event and wraps it in a custom event.
|
|
33
38
|
* @param {Event} event - This should be the change event that was listened for on an input element with `type="radio"`.
|
|
34
39
|
*/
|
|
35
|
-
private
|
|
40
|
+
private _handleChange;
|
|
36
41
|
/**
|
|
37
42
|
* (Read-only) returns a ValidityState with the validity states that this element is in.
|
|
38
43
|
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity
|
|
@@ -51,6 +56,10 @@ declare class PieRadio_2 extends PieRadio_base implements RadioProps {
|
|
|
51
56
|
|
|
52
57
|
declare const PieRadio_base: GenericConstructor<FormControlInterface> & GenericConstructor<RTLInterface> & typeof LitElement;
|
|
53
58
|
|
|
59
|
+
declare type PieRadioEvents = {
|
|
60
|
+
onChange?: (event: CustomEvent) => void;
|
|
61
|
+
};
|
|
62
|
+
|
|
54
63
|
export declare interface RadioProps {
|
|
55
64
|
/**
|
|
56
65
|
* The checked state of the radio.
|
package/dist/react.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import * as e from "react";
|
|
2
2
|
import { createComponent as o } from "@lit/react";
|
|
3
3
|
import { PieRadio as a } from "./index.js";
|
|
4
|
-
import { defaultProps as
|
|
4
|
+
import { defaultProps as s } from "./index.js";
|
|
5
5
|
const i = o({
|
|
6
6
|
displayName: "PieRadio",
|
|
7
7
|
elementClass: a,
|
|
8
8
|
react: e,
|
|
9
9
|
tagName: "pie-radio",
|
|
10
|
-
events: {
|
|
10
|
+
events: {
|
|
11
|
+
onChange: "change"
|
|
12
|
+
// when the radio state is changed.
|
|
13
|
+
}
|
|
11
14
|
}), m = i;
|
|
12
15
|
export {
|
|
13
16
|
m as PieRadio,
|
|
14
|
-
|
|
17
|
+
s as defaultProps
|
|
15
18
|
};
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { LitElement, html, unsafeCSS } from 'lit';
|
|
2
|
-
import { property, query } from 'lit/decorators.js';
|
|
2
|
+
import { property, query, state } from 'lit/decorators.js';
|
|
3
3
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
4
4
|
import { live } from 'lit/directives/live.js';
|
|
5
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
5
6
|
|
|
6
7
|
import {
|
|
7
|
-
defineCustomElement,
|
|
8
|
+
defineCustomElement,
|
|
9
|
+
FormControlMixin,
|
|
10
|
+
requiredProperty,
|
|
11
|
+
RtlMixin,
|
|
12
|
+
wrapNativeEvent,
|
|
8
13
|
} from '@justeattakeaway/pie-webc-core';
|
|
9
14
|
|
|
10
15
|
import { type RadioProps, defaultProps } from './defs';
|
|
@@ -17,8 +22,12 @@ const componentSelector = 'pie-radio';
|
|
|
17
22
|
|
|
18
23
|
/**
|
|
19
24
|
* @tagname pie-radio
|
|
25
|
+
* @event {CustomEvent} change - when the radio state is changed.
|
|
20
26
|
*/
|
|
21
27
|
export class PieRadio extends FormControlMixin(RtlMixin(LitElement)) implements RadioProps {
|
|
28
|
+
@state()
|
|
29
|
+
private _disabledByParent = false;
|
|
30
|
+
|
|
22
31
|
@property({ type: Boolean, reflect: true })
|
|
23
32
|
public checked = defaultProps.checked;
|
|
24
33
|
|
|
@@ -39,12 +48,27 @@ export class PieRadio extends FormControlMixin(RtlMixin(LitElement)) implements
|
|
|
39
48
|
public value!: RadioProps['value'];
|
|
40
49
|
|
|
41
50
|
@query('input[type="radio"]')
|
|
42
|
-
private
|
|
51
|
+
private _radio!: HTMLInputElement;
|
|
52
|
+
|
|
53
|
+
private _abortController!: AbortController;
|
|
54
|
+
|
|
55
|
+
connectedCallback () : void {
|
|
56
|
+
super.connectedCallback();
|
|
57
|
+
this._abortController = new AbortController();
|
|
58
|
+
const { signal } = this._abortController;
|
|
59
|
+
|
|
60
|
+
this.addEventListener('pie-radio-group-disabled', (e: CustomEventInit) => { this._disabledByParent = e.detail.disabled; }, { signal });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
disconnectedCallback () : void {
|
|
64
|
+
super.disconnectedCallback();
|
|
65
|
+
this._abortController.abort();
|
|
66
|
+
}
|
|
43
67
|
|
|
44
68
|
/**
|
|
45
69
|
* Ensures that the form value is in sync with the component.
|
|
46
70
|
*/
|
|
47
|
-
private
|
|
71
|
+
private _handleFormAssociation () {
|
|
48
72
|
if (this.form && this.name) {
|
|
49
73
|
this._internals.setFormValue(this.checked ? this.value : null);
|
|
50
74
|
}
|
|
@@ -54,7 +78,7 @@ export class PieRadio extends FormControlMixin(RtlMixin(LitElement)) implements
|
|
|
54
78
|
* Captures the native change event and wraps it in a custom event.
|
|
55
79
|
* @param {Event} event - This should be the change event that was listened for on an input element with `type="radio"`.
|
|
56
80
|
*/
|
|
57
|
-
private
|
|
81
|
+
private _handleChange (event: Event) {
|
|
58
82
|
const { checked } = event?.currentTarget as HTMLInputElement;
|
|
59
83
|
this.checked = checked;
|
|
60
84
|
// This is because some events set `composed` to `false`.
|
|
@@ -62,7 +86,7 @@ export class PieRadio extends FormControlMixin(RtlMixin(LitElement)) implements
|
|
|
62
86
|
const customChangeEvent = wrapNativeEvent(event);
|
|
63
87
|
this.dispatchEvent(customChangeEvent);
|
|
64
88
|
|
|
65
|
-
this.
|
|
89
|
+
this._handleFormAssociation();
|
|
66
90
|
}
|
|
67
91
|
|
|
68
92
|
/**
|
|
@@ -70,7 +94,7 @@ export class PieRadio extends FormControlMixin(RtlMixin(LitElement)) implements
|
|
|
70
94
|
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity
|
|
71
95
|
*/
|
|
72
96
|
public get validity () : ValidityState {
|
|
73
|
-
return this.
|
|
97
|
+
return this._radio.validity;
|
|
74
98
|
}
|
|
75
99
|
|
|
76
100
|
/**
|
|
@@ -88,30 +112,42 @@ export class PieRadio extends FormControlMixin(RtlMixin(LitElement)) implements
|
|
|
88
112
|
const changeEvent = new Event('change', { bubbles: true, composed: true });
|
|
89
113
|
this.dispatchEvent(changeEvent);
|
|
90
114
|
|
|
91
|
-
this.
|
|
115
|
+
this._handleFormAssociation();
|
|
92
116
|
}
|
|
93
117
|
|
|
94
118
|
updated () {
|
|
95
|
-
this.
|
|
119
|
+
this._handleFormAssociation();
|
|
96
120
|
}
|
|
97
121
|
|
|
98
122
|
render () {
|
|
99
123
|
const {
|
|
100
|
-
checked,
|
|
124
|
+
checked,
|
|
125
|
+
disabled,
|
|
126
|
+
_disabledByParent,
|
|
127
|
+
name,
|
|
128
|
+
required,
|
|
129
|
+
value,
|
|
101
130
|
} = this;
|
|
102
131
|
|
|
132
|
+
const componentDisabled = disabled || _disabledByParent;
|
|
133
|
+
|
|
134
|
+
const classes = {
|
|
135
|
+
'c-radio': true,
|
|
136
|
+
'c-radio--disabled': componentDisabled,
|
|
137
|
+
};
|
|
138
|
+
|
|
103
139
|
return html`
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
140
|
+
<label class=${classMap(classes)} for="radioId">
|
|
141
|
+
<input
|
|
142
|
+
type="radio"
|
|
143
|
+
id="radioId"
|
|
144
|
+
data-test-id="pie-radio"
|
|
145
|
+
.checked="${live(checked)}"
|
|
146
|
+
.value="${value}"
|
|
147
|
+
name="${ifDefined(name)}"
|
|
148
|
+
?disabled="${componentDisabled}"
|
|
149
|
+
?required="${required}"
|
|
150
|
+
@change="${this._handleChange}">
|
|
115
151
|
<slot></slot>
|
|
116
152
|
</label>`;
|
|
117
153
|
}
|
package/src/radio.scss
CHANGED
|
@@ -1 +1,145 @@
|
|
|
1
1
|
@use '@justeattakeaway/pie-css/scss' as p;
|
|
2
|
+
|
|
3
|
+
.c-radio {
|
|
4
|
+
--radio-dot-bg-color: var(--dt-color-content-interactive-primary);
|
|
5
|
+
--radio-bg-color: transparent;
|
|
6
|
+
--radio-bg-color--checked: var(--dt-color-interactive-brand);
|
|
7
|
+
--radio-border-color: var(--dt-color-interactive-form);
|
|
8
|
+
--radio-font-size: p.font-size(--dt-font-body-l-size);
|
|
9
|
+
--radio-font-weight: var(--dt-font-weight-regular);
|
|
10
|
+
--radio-text-color: var(--dt-color-content-default);
|
|
11
|
+
--radio-size: 24px;
|
|
12
|
+
--radio-dot-size: 8px;
|
|
13
|
+
--radio-cursor: pointer;
|
|
14
|
+
--radio-motion-easing: var(--dt-motion-easing-persistent-functional);
|
|
15
|
+
--radio-border-width: 1px;
|
|
16
|
+
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: var(--dt-spacing-b);
|
|
20
|
+
cursor: var(--radio-cursor);
|
|
21
|
+
font-size: var(--radio-font-size);
|
|
22
|
+
font-weight: var(--radio-font-weight);
|
|
23
|
+
color: var(--radio-text-color);
|
|
24
|
+
|
|
25
|
+
&.c-radio--disabled {
|
|
26
|
+
--radio-cursor: not-allowed;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
input[type="radio"] {
|
|
30
|
+
appearance: none;
|
|
31
|
+
display: block;
|
|
32
|
+
position: relative;
|
|
33
|
+
inline-size: var(--radio-size);
|
|
34
|
+
block-size: var(--radio-size);
|
|
35
|
+
border: var(--radio-border-width) solid var(--radio-border-color);
|
|
36
|
+
border-radius: 50%;
|
|
37
|
+
margin: 0;
|
|
38
|
+
cursor: var(--radio-cursor);
|
|
39
|
+
background-color: transparent;
|
|
40
|
+
transition: background-color var(--dt-motion-timing-100) var(--radio-motion-easing);
|
|
41
|
+
flex-shrink: 0;
|
|
42
|
+
|
|
43
|
+
&:focus {
|
|
44
|
+
@include p.focus;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// The filled circle before checking the radio
|
|
48
|
+
&:before {
|
|
49
|
+
--circle-size: calc(var(--radio-border-width) * -1);
|
|
50
|
+
|
|
51
|
+
content: '';
|
|
52
|
+
display: block;
|
|
53
|
+
inset: var(--circle-size);
|
|
54
|
+
border-radius: inherit;
|
|
55
|
+
background-color: var(--radio-bg-color--checked);
|
|
56
|
+
position: absolute;
|
|
57
|
+
transform: scale(0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&:not(:disabled):before {
|
|
61
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
62
|
+
transition: all var(--dt-motion-timing-100) var(--radio-motion-easing);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// The dot in the middle before checking the radio
|
|
67
|
+
&:after {
|
|
68
|
+
content: '';
|
|
69
|
+
position: absolute;
|
|
70
|
+
top: 50%;
|
|
71
|
+
left: 50%;
|
|
72
|
+
width: var(--radio-dot-size);
|
|
73
|
+
height: var(--radio-dot-size);
|
|
74
|
+
background-color: var(--radio-dot-bg-color);
|
|
75
|
+
border-radius: 50%;
|
|
76
|
+
transform: translate(-50%, -50%) scale(0);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
&:checked {
|
|
80
|
+
// The dot in the middle after checking the radio
|
|
81
|
+
&:after {
|
|
82
|
+
transform: translate(-50%, -50%) scale(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The filled circle after checking the radio
|
|
86
|
+
&:before {
|
|
87
|
+
transform: scale(1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Scales down at 100ms when unchecked
|
|
92
|
+
&:not(:disabled):after {
|
|
93
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
94
|
+
transition: all var(--dt-motion-timing-100) var(--radio-motion-easing);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Scales up at 150ms when checked
|
|
99
|
+
&:not(:disabled):checked:after {
|
|
100
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
101
|
+
transition: all var(--dt-motion-timing-150) var(--radio-motion-easing);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
&:disabled {
|
|
106
|
+
background-color: var(--dt-color-disabled-01);
|
|
107
|
+
border-color: var(--dt-color-border-default);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&:checked:disabled {
|
|
111
|
+
--radio-dot-bg-color: var(--dt-color-content-disabled);
|
|
112
|
+
--radio-bg-color--checked: var(--dt-color-disabled-01);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
&:hover:not(:checked, :disabled) {
|
|
116
|
+
background-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--dt-color-hover-01));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
&:active:not(:checked, :disabled) {
|
|
120
|
+
background-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--dt-color-active-01));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
&:hover:checked:not(:disabled) {
|
|
124
|
+
&:before {
|
|
125
|
+
background-color: hsl(var(--dt-color-interactive-brand-h),
|
|
126
|
+
var(--dt-color-interactive-brand-s),
|
|
127
|
+
calc(var(--dt-color-interactive-brand-l) - var(--dt-color-hover-01)));
|
|
128
|
+
border-color: hsl(var(--dt-color-interactive-brand-h),
|
|
129
|
+
var(--dt-color-interactive-brand-s),
|
|
130
|
+
calc(var(--dt-color-interactive-brand-l) - var(--dt-color-hover-01)));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
&:active:checked:not(:disabled) {
|
|
135
|
+
&:before {
|
|
136
|
+
background-color: hsl(var(--dt-color-interactive-brand-h),
|
|
137
|
+
var(--dt-color-interactive-brand-s),
|
|
138
|
+
calc(var(--dt-color-interactive-brand-l) - var(--dt-color-active-01)));
|
|
139
|
+
border-color: hsl(var(--dt-color-interactive-brand-h),
|
|
140
|
+
var(--dt-color-interactive-brand-s),
|
|
141
|
+
calc(var(--dt-color-interactive-brand-l) - var(--dt-color-active-01)));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
package/src/react.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { createComponent } from '@lit/react';
|
|
2
|
+
import { createComponent, type EventName } from '@lit/react';
|
|
3
3
|
import { PieRadio as PieRadioLit } from './index';
|
|
4
4
|
import { type RadioProps } from './defs';
|
|
5
5
|
|
|
@@ -10,10 +10,16 @@ const PieRadioReact = createComponent({
|
|
|
10
10
|
elementClass: PieRadioLit,
|
|
11
11
|
react: React,
|
|
12
12
|
tagName: 'pie-radio',
|
|
13
|
-
events: {
|
|
13
|
+
events: {
|
|
14
|
+
onChange: 'change' as EventName<CustomEvent>, // when the radio state is changed.
|
|
15
|
+
},
|
|
14
16
|
});
|
|
15
17
|
|
|
16
18
|
type ReactBaseType = React.InputHTMLAttributes<HTMLInputElement>;
|
|
17
19
|
|
|
20
|
+
type PieRadioEvents = {
|
|
21
|
+
onChange?: (event: CustomEvent) => void;
|
|
22
|
+
};
|
|
23
|
+
|
|
18
24
|
export const PieRadio = PieRadioReact as React.ForwardRefExoticComponent<React.PropsWithoutRef<RadioProps>
|
|
19
|
-
& React.RefAttributes<PieRadioLit> & ReactBaseType>;
|
|
25
|
+
& React.RefAttributes<PieRadioLit> & PieRadioEvents & ReactBaseType>;
|