@justeattakeaway/pie-checkbox 0.3.1 → 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.
@@ -18,7 +18,7 @@
18
18
  "type": {
19
19
  "text": "DefaultProps"
20
20
  },
21
- "default": "{\n required: false,\n indeterminate: false,\n}"
21
+ "default": "{\n // a default value for the html <input type=\"checkbox\" /> value attribute.\n // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#value\n value: 'on',\n required: false,\n indeterminate: false,\n checked: false,\n}"
22
22
  }
23
23
  ],
24
24
  "exports": [
@@ -40,12 +40,6 @@
40
40
  "kind": "class",
41
41
  "description": "",
42
42
  "name": "PieCheckbox",
43
- "slots": [
44
- {
45
- "description": "Default slot (checkbox label)",
46
- "name": ""
47
- }
48
- ],
49
43
  "members": [
50
44
  {
51
45
  "kind": "field",
@@ -59,9 +53,6 @@
59
53
  {
60
54
  "kind": "field",
61
55
  "name": "value",
62
- "type": {
63
- "text": "CheckboxProps['value']"
64
- },
65
56
  "privacy": "public",
66
57
  "attribute": "value"
67
58
  },
@@ -86,11 +77,9 @@
86
77
  {
87
78
  "kind": "field",
88
79
  "name": "checked",
89
- "type": {
90
- "text": "CheckboxProps['checked'] | undefined"
91
- },
92
80
  "privacy": "public",
93
- "attribute": "checked"
81
+ "attribute": "checked",
82
+ "reflects": true
94
83
  },
95
84
  {
96
85
  "kind": "field",
@@ -119,7 +108,8 @@
119
108
  "text": "CheckboxProps['indeterminate'] | undefined"
120
109
  },
121
110
  "privacy": "public",
122
- "attribute": "indeterminate"
111
+ "attribute": "indeterminate",
112
+ "reflects": true
123
113
  },
124
114
  {
125
115
  "kind": "field",
@@ -149,27 +139,64 @@
149
139
  "readonly": true
150
140
  },
151
141
  {
152
- "kind": "field",
142
+ "kind": "method",
143
+ "name": "handleFormAssociation",
144
+ "privacy": "private",
145
+ "return": {
146
+ "type": {
147
+ "text": "void"
148
+ }
149
+ },
150
+ "description": "Ensures that the form value is in sync with the component."
151
+ },
152
+ {
153
+ "kind": "method",
154
+ "name": "formDisabledCallback",
155
+ "privacy": "public",
156
+ "return": {
157
+ "type": {
158
+ "text": "void"
159
+ }
160
+ },
161
+ "parameters": [
162
+ {
163
+ "name": "disabled",
164
+ "type": {
165
+ "text": "boolean"
166
+ },
167
+ "description": "The latest disabled state of the input."
168
+ }
169
+ ],
170
+ "description": "Called after the disabled state of the element changes,\neither because the disabled attribute of this element was added or removed;\nor because the disabled state changed on a <fieldset> that's an ancestor of this element."
171
+ },
172
+ {
173
+ "kind": "method",
153
174
  "name": "handleChange",
154
175
  "privacy": "private",
155
- "description": "The onChange function updates the checkbox state and emits an event for consumers.",
156
176
  "parameters": [
157
177
  {
158
- "description": "This should be the change event that was listened for on an input element with `type=\"checkbox\"`.",
159
178
  "name": "event",
160
179
  "type": {
161
180
  "text": "Event"
162
- }
181
+ },
182
+ "description": "This should be the change event that was listened for on an input element with `type=\"checkbox\"`."
163
183
  }
164
- ]
184
+ ],
185
+ "description": "Captures the native change event and wraps it in a custom event."
165
186
  }
166
187
  ],
167
- "attributes": [
188
+ "events": [
168
189
  {
169
- "name": "value",
170
190
  "type": {
171
- "text": "CheckboxProps['value']"
191
+ "text": "CustomEvent"
172
192
  },
193
+ "description": "when checked state is changed.",
194
+ "name": "change"
195
+ }
196
+ ],
197
+ "attributes": [
198
+ {
199
+ "name": "value",
173
200
  "fieldName": "value"
174
201
  },
175
202
  {
@@ -188,9 +215,6 @@
188
215
  },
189
216
  {
190
217
  "name": "checked",
191
- "type": {
192
- "text": "CheckboxProps['checked'] | undefined"
193
- },
194
218
  "fieldName": "checked"
195
219
  },
196
220
  {
@@ -223,6 +247,10 @@
223
247
  }
224
248
  ],
225
249
  "mixins": [
250
+ {
251
+ "name": "FormControlMixin",
252
+ "package": "@justeattakeaway/pie-webc-core"
253
+ },
226
254
  {
227
255
  "name": "RtlMixin",
228
256
  "package": "@justeattakeaway/pie-webc-core"
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
2
2
  import type { CSSResult } from 'lit';
3
+ import type { FormControlInterface } from '@justeattakeaway/pie-webc-core';
3
4
  import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
4
5
  import type { LitElement } from 'lit';
6
+ import type { PropertyValues } from 'lit';
5
7
  import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
6
8
  import type { TemplateResult } from 'lit-html';
7
9
 
@@ -29,7 +31,7 @@ export declare interface CheckboxProps {
29
31
  */
30
32
  disabled?: boolean;
31
33
  /**
32
- * Same as the HTML checked attribute - indicates whether or not the checkbox is checked by default (when the page loads).
34
+ * Indicates whether or not the checkbox is checked.
33
35
  */
34
36
  checked?: boolean;
35
37
  /**
@@ -47,13 +49,13 @@ export declare interface CheckboxProps {
47
49
  aria?: AriaProps;
48
50
  }
49
51
 
50
- export declare type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'required' | 'indeterminate'>;
52
+ export declare type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'value' | 'required' | 'indeterminate' | 'checked'>;
51
53
 
52
54
  export declare const defaultProps: DefaultProps;
53
55
 
54
56
  /**
55
57
  * @tagname pie-checkbox
56
- * @slot - Default slot (checkbox label)
58
+ * @event {CustomEvent} change - when checked state is changed.
57
59
  */
58
60
  export declare class PieCheckbox extends PieCheckbox_base implements CheckboxProps {
59
61
  static shadowRootOptions: {
@@ -61,10 +63,10 @@ export declare class PieCheckbox extends PieCheckbox_base implements CheckboxPro
61
63
  mode: ShadowRootMode;
62
64
  slotAssignment?: SlotAssignmentMode | undefined;
63
65
  };
64
- value: CheckboxProps['value'];
66
+ value: string;
65
67
  label?: CheckboxProps['label'];
66
68
  name?: CheckboxProps['name'];
67
- checked?: CheckboxProps['checked'];
69
+ checked: boolean;
68
70
  disabled?: CheckboxProps['disabled'];
69
71
  required?: CheckboxProps['required'];
70
72
  indeterminate?: CheckboxProps['indeterminate'];
@@ -76,7 +78,20 @@ export declare class PieCheckbox extends PieCheckbox_base implements CheckboxPro
76
78
  */
77
79
  get validity(): ValidityState;
78
80
  /**
79
- * The onChange function updates the checkbox state and emits an event for consumers.
81
+ * Ensures that the form value is in sync with the component.
82
+ */
83
+ private handleFormAssociation;
84
+ /**
85
+ * Called after the disabled state of the element changes,
86
+ * either because the disabled attribute of this element was added or removed;
87
+ * or because the disabled state changed on a <fieldset> that's an ancestor of this element.
88
+ * @param disabled - The latest disabled state of the input.
89
+ */
90
+ formDisabledCallback(disabled: boolean): void;
91
+ protected firstUpdated(_changedProperties: PropertyValues<this>): void;
92
+ protected updated(_changedProperties: PropertyValues<this>): void;
93
+ /**
94
+ * Captures the native change event and wraps it in a custom event.
80
95
  * @param {Event} event - This should be the change event that was listened for on an input element with `type="checkbox"`.
81
96
  */
82
97
  private handleChange;
@@ -84,6 +99,6 @@ export declare class PieCheckbox extends PieCheckbox_base implements CheckboxPro
84
99
  static styles: CSSResult;
85
100
  }
86
101
 
87
- declare const PieCheckbox_base: GenericConstructor<RTLInterface> & typeof LitElement;
102
+ declare const PieCheckbox_base: GenericConstructor<FormControlInterface> & GenericConstructor<RTLInterface> & typeof LitElement;
88
103
 
89
104
  export { }
package/dist/index.js CHANGED
@@ -1,24 +1,26 @@
1
- import { LitElement as y, html as m, nothing as d, unsafeCSS as f } from "lit";
2
- import { RtlMixin as v, wrapNativeEvent as g, defineCustomElement as $ } from "@justeattakeaway/pie-webc-core";
3
- import { property as n, query as x } from "lit/decorators.js";
4
- import { ifDefined as h } from "lit/directives/if-defined.js";
5
- const q = `*,*:after,*:before{box-sizing:inherit}
6
- `, b = {
1
+ import { LitElement as u, html as b, nothing as d, unsafeCSS as f } from "lit";
2
+ import { FormControlMixin as y, RtlMixin as v, wrapNativeEvent as g, defineCustomElement as k } from "@justeattakeaway/pie-webc-core";
3
+ import { live as x } from "lit/directives/live.js";
4
+ import { property as a, query as $ } from "lit/decorators.js";
5
+ import { ifDefined as C } from "lit/directives/if-defined.js";
6
+ const F = `*,*:after,*:before{box-sizing:inherit}
7
+ `, p = {
8
+ // a default value for the html <input type="checkbox" /> value attribute.
9
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#value
10
+ value: "on",
7
11
  required: !1,
8
- indeterminate: !1
12
+ indeterminate: !1,
13
+ checked: !1
9
14
  };
10
- var C = Object.defineProperty, O = Object.getOwnPropertyDescriptor, o = (c, i, p, a) => {
11
- for (var t = a > 1 ? void 0 : a ? O(i, p) : i, l = c.length - 1, s; l >= 0; l--)
12
- (s = c[l]) && (t = (a ? s(i, p, t) : s(t)) || t);
13
- return a && t && C(i, p, t), t;
15
+ var _ = Object.defineProperty, q = Object.getOwnPropertyDescriptor, i = (h, e, n, s) => {
16
+ for (var o = s > 1 ? void 0 : s ? q(e, n) : e, l = h.length - 1, c; l >= 0; l--)
17
+ (c = h[l]) && (o = (s ? c(e, n, o) : c(o)) || o);
18
+ return s && o && _(e, n, o), o;
14
19
  };
15
- const P = "pie-checkbox";
16
- class e extends v(y) {
20
+ const O = "pie-checkbox";
21
+ class t extends y(v(u)) {
17
22
  constructor() {
18
- super(...arguments), this.required = b.required, this.indeterminate = b.indeterminate, this.handleChange = (i) => {
19
- const p = g(i);
20
- this.dispatchEvent(p);
21
- };
23
+ super(...arguments), this.value = p.value, this.checked = p.checked, this.required = p.required, this.indeterminate = p.indeterminate;
22
24
  }
23
25
  /**
24
26
  * (Read-only) returns a ValidityState with the validity states that this element is in.
@@ -27,68 +29,99 @@ class e extends v(y) {
27
29
  get validity() {
28
30
  return this.checkbox.validity;
29
31
  }
32
+ /**
33
+ * Ensures that the form value is in sync with the component.
34
+ */
35
+ handleFormAssociation() {
36
+ !!this._internals.form && !!this.name && this._internals.setFormValue(this.checked ? this.value : null);
37
+ }
38
+ /**
39
+ * Called after the disabled state of the element changes,
40
+ * either because the disabled attribute of this element was added or removed;
41
+ * or because the disabled state changed on a <fieldset> that's an ancestor of this element.
42
+ * @param disabled - The latest disabled state of the input.
43
+ */
44
+ formDisabledCallback(e) {
45
+ this.disabled = e;
46
+ }
47
+ firstUpdated(e) {
48
+ super.firstUpdated(e), this.handleFormAssociation();
49
+ }
50
+ updated(e) {
51
+ super.updated(e), this.handleFormAssociation();
52
+ }
53
+ /**
54
+ * Captures the native change event and wraps it in a custom event.
55
+ * @param {Event} event - This should be the change event that was listened for on an input element with `type="checkbox"`.
56
+ */
57
+ handleChange(e) {
58
+ const { checked: n } = e == null ? void 0 : e.currentTarget;
59
+ this.checked = n;
60
+ const s = g(e);
61
+ this.dispatchEvent(s), this.handleFormAssociation();
62
+ }
30
63
  render() {
31
64
  const {
32
- checked: i,
33
- value: p,
34
- name: a,
35
- label: t,
65
+ checked: e,
66
+ value: n,
67
+ name: s,
68
+ label: o,
36
69
  disabled: l,
37
- required: s,
38
- indeterminate: u,
70
+ required: c,
71
+ indeterminate: m,
39
72
  aria: r
40
73
  } = this;
41
- return m`
42
- <label>
74
+ return b`
75
+ <label data-test-id="checkbox-component">
43
76
  <input
44
77
  type="checkbox"
45
- ?checked=${h(i)}
46
- .value=${h(p)}
47
- name=${h(a)}
78
+ .value=${n}
79
+ ?checked=${x(e)}
80
+ name=${C(s)}
48
81
  ?disabled=${l}
49
- ?required=${s}
50
- .indeterminate=${u}
82
+ ?required=${c}
83
+ .indeterminate=${m}
51
84
  aria-label=${(r == null ? void 0 : r.label) || d}
52
- aria-labelledby=${t ? d : (r == null ? void 0 : r.labelledby) || d}
85
+ aria-labelledby=${o ? d : (r == null ? void 0 : r.labelledby) || d}
53
86
  aria-describedby= ${(r == null ? void 0 : r.describedby) || d}
54
87
  @change=${this.handleChange}
55
- data-test-id="pie-checkbox"
88
+ data-test-id="checkbox-input"
56
89
  />
57
- ${t}
90
+ ${o}
58
91
  </label>`;
59
92
  }
60
93
  }
61
- e.shadowRootOptions = { ...y.shadowRootOptions, delegatesFocus: !0 };
62
- e.styles = f(q);
63
- o([
64
- n({ type: String })
65
- ], e.prototype, "value", 2);
66
- o([
67
- n({ type: String })
68
- ], e.prototype, "label", 2);
69
- o([
70
- n({ type: String })
71
- ], e.prototype, "name", 2);
72
- o([
73
- n({ type: Boolean })
74
- ], e.prototype, "checked", 2);
75
- o([
76
- n({ type: Boolean, reflect: !0 })
77
- ], e.prototype, "disabled", 2);
78
- o([
79
- n({ type: Boolean, reflect: !0 })
80
- ], e.prototype, "required", 2);
81
- o([
82
- n({ type: Boolean })
83
- ], e.prototype, "indeterminate", 2);
84
- o([
85
- n({ type: Object })
86
- ], e.prototype, "aria", 2);
87
- o([
88
- x("input")
89
- ], e.prototype, "checkbox", 2);
90
- $(P, e);
94
+ t.shadowRootOptions = { ...u.shadowRootOptions, delegatesFocus: !0 };
95
+ t.styles = f(F);
96
+ i([
97
+ a({ type: String })
98
+ ], t.prototype, "value", 2);
99
+ i([
100
+ a({ type: String })
101
+ ], t.prototype, "label", 2);
102
+ i([
103
+ a({ type: String })
104
+ ], t.prototype, "name", 2);
105
+ i([
106
+ a({ type: Boolean, reflect: !0 })
107
+ ], t.prototype, "checked", 2);
108
+ i([
109
+ a({ type: Boolean, reflect: !0 })
110
+ ], t.prototype, "disabled", 2);
111
+ i([
112
+ a({ type: Boolean, reflect: !0 })
113
+ ], t.prototype, "required", 2);
114
+ i([
115
+ a({ type: Boolean, reflect: !0 })
116
+ ], t.prototype, "indeterminate", 2);
117
+ i([
118
+ a({ type: Object })
119
+ ], t.prototype, "aria", 2);
120
+ i([
121
+ $('input[type="checkbox"]')
122
+ ], t.prototype, "checkbox", 2);
123
+ k(O, t);
91
124
  export {
92
- e as PieCheckbox,
93
- b as defaultProps
125
+ t as PieCheckbox,
126
+ p as defaultProps
94
127
  };
package/dist/react.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
2
2
  import type { CSSResult } from 'lit';
3
+ import type { FormControlInterface } from '@justeattakeaway/pie-webc-core';
3
4
  import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
4
5
  import type { LitElement } from 'lit';
6
+ import type { PropertyValues } from 'lit';
5
7
  import * as React_2 from 'react';
6
8
  import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
7
9
  import type { TemplateResult } from 'lit-html';
@@ -30,7 +32,7 @@ export declare interface CheckboxProps {
30
32
  */
31
33
  disabled?: boolean;
32
34
  /**
33
- * Same as the HTML checked attribute - indicates whether or not the checkbox is checked by default (when the page loads).
35
+ * Indicates whether or not the checkbox is checked.
34
36
  */
35
37
  checked?: boolean;
36
38
  /**
@@ -48,15 +50,15 @@ export declare interface CheckboxProps {
48
50
  aria?: AriaProps;
49
51
  }
50
52
 
51
- export declare type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'required' | 'indeterminate'>;
53
+ export declare type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'value' | 'required' | 'indeterminate' | 'checked'>;
52
54
 
53
55
  export declare const defaultProps: DefaultProps;
54
56
 
55
- export declare const PieCheckbox: React_2.ForwardRefExoticComponent<CheckboxProps & React_2.RefAttributes<PieCheckbox_2> & ReactBaseType>;
57
+ export declare const PieCheckbox: React_2.ForwardRefExoticComponent<CheckboxProps & React_2.RefAttributes<PieCheckbox_2> & PieCheckboxEvents & ReactBaseType>;
56
58
 
57
59
  /**
58
60
  * @tagname pie-checkbox
59
- * @slot - Default slot (checkbox label)
61
+ * @event {CustomEvent} change - when checked state is changed.
60
62
  */
61
63
  declare class PieCheckbox_2 extends PieCheckbox_base implements CheckboxProps {
62
64
  static shadowRootOptions: {
@@ -64,10 +66,10 @@ declare class PieCheckbox_2 extends PieCheckbox_base implements CheckboxProps {
64
66
  mode: ShadowRootMode;
65
67
  slotAssignment?: SlotAssignmentMode | undefined;
66
68
  };
67
- value: CheckboxProps['value'];
69
+ value: string;
68
70
  label?: CheckboxProps['label'];
69
71
  name?: CheckboxProps['name'];
70
- checked?: CheckboxProps['checked'];
72
+ checked: boolean;
71
73
  disabled?: CheckboxProps['disabled'];
72
74
  required?: CheckboxProps['required'];
73
75
  indeterminate?: CheckboxProps['indeterminate'];
@@ -79,7 +81,20 @@ declare class PieCheckbox_2 extends PieCheckbox_base implements CheckboxProps {
79
81
  */
80
82
  get validity(): ValidityState;
81
83
  /**
82
- * The onChange function updates the checkbox state and emits an event for consumers.
84
+ * Ensures that the form value is in sync with the component.
85
+ */
86
+ private handleFormAssociation;
87
+ /**
88
+ * Called after the disabled state of the element changes,
89
+ * either because the disabled attribute of this element was added or removed;
90
+ * or because the disabled state changed on a <fieldset> that's an ancestor of this element.
91
+ * @param disabled - The latest disabled state of the input.
92
+ */
93
+ formDisabledCallback(disabled: boolean): void;
94
+ protected firstUpdated(_changedProperties: PropertyValues<this>): void;
95
+ protected updated(_changedProperties: PropertyValues<this>): void;
96
+ /**
97
+ * Captures the native change event and wraps it in a custom event.
83
98
  * @param {Event} event - This should be the change event that was listened for on an input element with `type="checkbox"`.
84
99
  */
85
100
  private handleChange;
@@ -87,8 +102,12 @@ declare class PieCheckbox_2 extends PieCheckbox_base implements CheckboxProps {
87
102
  static styles: CSSResult;
88
103
  }
89
104
 
90
- declare const PieCheckbox_base: GenericConstructor<RTLInterface> & typeof LitElement;
105
+ declare const PieCheckbox_base: GenericConstructor<FormControlInterface> & GenericConstructor<RTLInterface> & typeof LitElement;
106
+
107
+ declare type PieCheckboxEvents = {
108
+ onChange?: (event: CustomEvent) => void;
109
+ };
91
110
 
92
- declare type ReactBaseType = React_2.HTMLAttributes<HTMLElement>;
111
+ declare type ReactBaseType = React_2.InputHTMLAttributes<HTMLInputElement>;
93
112
 
94
113
  export { }
package/dist/react.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import * as e from "react";
2
2
  import { createComponent as o } from "@lit/react";
3
3
  import { PieCheckbox as t } from "./index.js";
4
- import { defaultProps as h } from "./index.js";
4
+ import { defaultProps as b } from "./index.js";
5
5
  import "lit";
6
6
  import "@justeattakeaway/pie-webc-core";
7
+ import "lit/directives/live.js";
7
8
  import "lit/decorators.js";
8
9
  import "lit/directives/if-defined.js";
9
10
  const r = o({
@@ -11,9 +12,12 @@ const r = o({
11
12
  elementClass: t,
12
13
  react: e,
13
14
  tagName: "pie-checkbox",
14
- events: {}
15
- }), x = r;
15
+ events: {
16
+ onChange: "change"
17
+ // when checked state is changed.
18
+ }
19
+ }), h = r;
16
20
  export {
17
- x as PieCheckbox,
18
- h as defaultProps
21
+ h as PieCheckbox,
22
+ b as defaultProps
19
23
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-checkbox",
3
3
  "description": "PIE Design System Checkbox built using Web Components",
4
- "version": "0.3.1",
4
+ "version": "0.4.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
package/src/defs-react.ts CHANGED
@@ -1,8 +1,3 @@
1
1
  import React from 'react';
2
- /**
3
- * TODO: Verify if ReactBaseType can be set as a more specific React interface
4
- * Use the React IntrinsicElements interface to find how to map standard HTML elements to existing React Interfaces
5
- * Example: an HTML button maps to `React.ButtonHTMLAttributes<HTMLButtonElement>`
6
- * https://github.com/DefinitelyTyped/DefinitelyTyped/blob/0bb210867d16170c4a08d9ce5d132817651a0f80/types/react/index.d.ts#L2829
7
- */
8
- export type ReactBaseType = React.HTMLAttributes<HTMLElement>
2
+
3
+ export type ReactBaseType = React.InputHTMLAttributes<HTMLInputElement>
package/src/defs.ts CHANGED
@@ -27,7 +27,7 @@ export interface CheckboxProps {
27
27
  disabled?: boolean;
28
28
 
29
29
  /**
30
- * Same as the HTML checked attribute - indicates whether or not the checkbox is checked by default (when the page loads).
30
+ * Indicates whether or not the checkbox is checked.
31
31
  */
32
32
  checked?: boolean;
33
33
 
@@ -48,10 +48,14 @@ export interface CheckboxProps {
48
48
  aria?: AriaProps;
49
49
  }
50
50
 
51
- export type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'required' | 'indeterminate'>;
51
+ export type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'value' | 'required' | 'indeterminate' | 'checked' >;
52
52
 
53
53
  export const defaultProps: DefaultProps = {
54
+ // a default value for the html <input type="checkbox" /> value attribute.
55
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#value
56
+ value: 'on',
54
57
  required: false,
55
58
  indeterminate: false,
59
+ checked: false,
56
60
  };
57
61
 
package/src/index.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import {
2
- LitElement, html, unsafeCSS, nothing,
2
+ LitElement, html, unsafeCSS, PropertyValues, nothing,
3
3
  } from 'lit';
4
4
  import {
5
5
  RtlMixin,
6
6
  defineCustomElement,
7
7
  wrapNativeEvent,
8
+ FormControlMixin,
8
9
  } from '@justeattakeaway/pie-webc-core';
10
+ import { live } from 'lit/directives/live.js';
9
11
  import { property, query } from 'lit/decorators.js';
10
12
  import { ifDefined } from 'lit/directives/if-defined.js';
11
13
 
@@ -19,13 +21,13 @@ const componentSelector = 'pie-checkbox';
19
21
 
20
22
  /**
21
23
  * @tagname pie-checkbox
22
- * @slot - Default slot (checkbox label)
24
+ * @event {CustomEvent} change - when checked state is changed.
23
25
  */
24
- export class PieCheckbox extends RtlMixin(LitElement) implements CheckboxProps {
26
+ export class PieCheckbox extends FormControlMixin(RtlMixin(LitElement)) implements CheckboxProps {
25
27
  static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };
26
28
 
27
29
  @property({ type: String })
28
- public value: CheckboxProps['value'];
30
+ public value = defaultProps.value;
29
31
 
30
32
  @property({ type: String })
31
33
  public label?: CheckboxProps['label'];
@@ -33,8 +35,8 @@ export class PieCheckbox extends RtlMixin(LitElement) implements CheckboxProps {
33
35
  @property({ type: String })
34
36
  public name?: CheckboxProps['name'];
35
37
 
36
- @property({ type: Boolean })
37
- public checked?: CheckboxProps['checked'];
38
+ @property({ type: Boolean, reflect: true })
39
+ public checked = defaultProps.checked;
38
40
 
39
41
  @property({ type: Boolean, reflect: true })
40
42
  public disabled?: CheckboxProps['disabled'];
@@ -42,13 +44,13 @@ export class PieCheckbox extends RtlMixin(LitElement) implements CheckboxProps {
42
44
  @property({ type: Boolean, reflect: true })
43
45
  public required?: CheckboxProps['required'] = defaultProps.required;
44
46
 
45
- @property({ type: Boolean })
47
+ @property({ type: Boolean, reflect: true })
46
48
  public indeterminate?: CheckboxProps['indeterminate'] = defaultProps.indeterminate;
47
49
 
48
50
  @property({ type: Object })
49
51
  public aria: CheckboxProps['aria'];
50
52
 
51
- @query('input')
53
+ @query('input[type="checkbox"]')
52
54
  private checkbox?: HTMLInputElement;
53
55
 
54
56
  /**
@@ -60,16 +62,51 @@ export class PieCheckbox extends RtlMixin(LitElement) implements CheckboxProps {
60
62
  }
61
63
 
62
64
  /**
63
- * The onChange function updates the checkbox state and emits an event for consumers.
65
+ * Ensures that the form value is in sync with the component.
66
+ */
67
+ private handleFormAssociation () : void {
68
+ const isFormAssociated = !!this._internals.form && !!this.name;
69
+ if (isFormAssociated) {
70
+ this._internals.setFormValue(this.checked ? this.value : null);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Called after the disabled state of the element changes,
76
+ * either because the disabled attribute of this element was added or removed;
77
+ * or because the disabled state changed on a <fieldset> that's an ancestor of this element.
78
+ * @param disabled - The latest disabled state of the input.
79
+ */
80
+ public formDisabledCallback (disabled: boolean): void {
81
+ this.disabled = disabled;
82
+ }
83
+
84
+ protected firstUpdated (_changedProperties: PropertyValues<this>): void {
85
+ super.firstUpdated(_changedProperties);
86
+
87
+ this.handleFormAssociation();
88
+ }
89
+
90
+ protected updated (_changedProperties: PropertyValues<this>): void {
91
+ super.updated(_changedProperties);
92
+
93
+ this.handleFormAssociation();
94
+ }
95
+
96
+ /**
97
+ * Captures the native change event and wraps it in a custom event.
64
98
  * @param {Event} event - This should be the change event that was listened for on an input element with `type="checkbox"`.
65
99
  */
66
- private handleChange = (event: Event) => {
100
+ private handleChange (event: Event) {
101
+ const { checked } = event?.currentTarget as HTMLInputElement;
102
+ this.checked = checked;
67
103
  // This is because some events set `composed` to `false`.
68
104
  // Reference: https://javascript.info/shadow-dom-events#event-composed
69
105
  const customChangeEvent = wrapNativeEvent(event);
70
-
71
106
  this.dispatchEvent(customChangeEvent);
72
- };
107
+
108
+ this.handleFormAssociation();
109
+ }
73
110
 
74
111
  render () {
75
112
  const {
@@ -84,11 +121,11 @@ export class PieCheckbox extends RtlMixin(LitElement) implements CheckboxProps {
84
121
  } = this;
85
122
 
86
123
  return html`
87
- <label>
124
+ <label data-test-id="checkbox-component">
88
125
  <input
89
126
  type="checkbox"
90
- ?checked=${ifDefined(checked)}
91
- .value=${ifDefined(value)}
127
+ .value=${value}
128
+ ?checked=${live(checked)}
92
129
  name=${ifDefined(name)}
93
130
  ?disabled=${disabled}
94
131
  ?required=${required}
@@ -97,7 +134,7 @@ export class PieCheckbox extends RtlMixin(LitElement) implements CheckboxProps {
97
134
  aria-labelledby=${label ? nothing : aria?.labelledby || nothing}
98
135
  aria-describedby= ${aria?.describedby || nothing}
99
136
  @change=${this.handleChange}
100
- data-test-id="pie-checkbox"
137
+ data-test-id="checkbox-input"
101
138
  />
102
139
  ${label}
103
140
  </label>`;
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, EventName } from '@lit/react';
3
3
  import { PieCheckbox as PieCheckboxLit } from './index';
4
4
  import { CheckboxProps } from './defs';
5
5
 
@@ -10,10 +10,16 @@ const PieCheckboxReact = createComponent({
10
10
  elementClass: PieCheckboxLit,
11
11
  react: React,
12
12
  tagName: 'pie-checkbox',
13
- events: {},
13
+ events: {
14
+ onChange: 'change' as EventName<CustomEvent>, // when checked state is changed.
15
+ },
14
16
  });
15
17
 
16
- type ReactBaseType = React.HTMLAttributes<HTMLElement>
18
+ type ReactBaseType = React.InputHTMLAttributes<HTMLInputElement>
19
+
20
+ type PieCheckboxEvents = {
21
+ onChange?: (event: CustomEvent) => void;
22
+ };
17
23
 
18
24
  export const PieCheckbox = PieCheckboxReact as React.ForwardRefExoticComponent<React.PropsWithoutRef<CheckboxProps>
19
- & React.RefAttributes<PieCheckboxLit> & ReactBaseType>;
25
+ & React.RefAttributes<PieCheckboxLit> & PieCheckboxEvents & ReactBaseType>;