@justeattakeaway/pie-checkbox 0.3.0 → 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.
@@ -11,8 +11,26 @@
11
11
  {
12
12
  "kind": "javascript-module",
13
13
  "path": "src/defs.js",
14
- "declarations": [],
15
- "exports": []
14
+ "declarations": [
15
+ {
16
+ "kind": "variable",
17
+ "name": "defaultProps",
18
+ "type": {
19
+ "text": "DefaultProps"
20
+ },
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
+ }
23
+ ],
24
+ "exports": [
25
+ {
26
+ "kind": "js",
27
+ "name": "defaultProps",
28
+ "declaration": {
29
+ "name": "defaultProps",
30
+ "module": "src/defs.js"
31
+ }
32
+ }
33
+ ]
16
34
  },
17
35
  {
18
36
  "kind": "javascript-module",
@@ -22,12 +40,6 @@
22
40
  "kind": "class",
23
41
  "description": "",
24
42
  "name": "PieCheckbox",
25
- "slots": [
26
- {
27
- "description": "Default slot (checkbox label)",
28
- "name": ""
29
- }
30
- ],
31
43
  "members": [
32
44
  {
33
45
  "kind": "field",
@@ -41,9 +53,6 @@
41
53
  {
42
54
  "kind": "field",
43
55
  "name": "value",
44
- "type": {
45
- "text": "CheckboxProps['value']"
46
- },
47
56
  "privacy": "public",
48
57
  "attribute": "value"
49
58
  },
@@ -68,11 +77,9 @@
68
77
  {
69
78
  "kind": "field",
70
79
  "name": "checked",
71
- "type": {
72
- "text": "CheckboxProps['checked'] | undefined"
73
- },
74
80
  "privacy": "public",
75
- "attribute": "checked"
81
+ "attribute": "checked",
82
+ "reflects": true
76
83
  },
77
84
  {
78
85
  "kind": "field",
@@ -91,7 +98,6 @@
91
98
  "text": "CheckboxProps['required'] | undefined"
92
99
  },
93
100
  "privacy": "public",
94
- "default": "false",
95
101
  "attribute": "required",
96
102
  "reflects": true
97
103
  },
@@ -102,8 +108,8 @@
102
108
  "text": "CheckboxProps['indeterminate'] | undefined"
103
109
  },
104
110
  "privacy": "public",
105
- "default": "false",
106
- "attribute": "indeterminate"
111
+ "attribute": "indeterminate",
112
+ "reflects": true
107
113
  },
108
114
  {
109
115
  "kind": "field",
@@ -133,27 +139,64 @@
133
139
  "readonly": true
134
140
  },
135
141
  {
136
- "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",
137
174
  "name": "handleChange",
138
175
  "privacy": "private",
139
- "description": "The onChange function updates the checkbox state and emits an event for consumers.",
140
176
  "parameters": [
141
177
  {
142
- "description": "This should be the change event that was listened for on an input element with `type=\"checkbox\"`.",
143
178
  "name": "event",
144
179
  "type": {
145
180
  "text": "Event"
146
- }
181
+ },
182
+ "description": "This should be the change event that was listened for on an input element with `type=\"checkbox\"`."
147
183
  }
148
- ]
184
+ ],
185
+ "description": "Captures the native change event and wraps it in a custom event."
149
186
  }
150
187
  ],
151
- "attributes": [
188
+ "events": [
152
189
  {
153
- "name": "value",
154
190
  "type": {
155
- "text": "CheckboxProps['value']"
191
+ "text": "CustomEvent"
156
192
  },
193
+ "description": "when checked state is changed.",
194
+ "name": "change"
195
+ }
196
+ ],
197
+ "attributes": [
198
+ {
199
+ "name": "value",
157
200
  "fieldName": "value"
158
201
  },
159
202
  {
@@ -172,9 +215,6 @@
172
215
  },
173
216
  {
174
217
  "name": "checked",
175
- "type": {
176
- "text": "CheckboxProps['checked'] | undefined"
177
- },
178
218
  "fieldName": "checked"
179
219
  },
180
220
  {
@@ -189,7 +229,6 @@
189
229
  "type": {
190
230
  "text": "CheckboxProps['required'] | undefined"
191
231
  },
192
- "default": "false",
193
232
  "fieldName": "required"
194
233
  },
195
234
  {
@@ -197,7 +236,6 @@
197
236
  "type": {
198
237
  "text": "CheckboxProps['indeterminate'] | undefined"
199
238
  },
200
- "default": "false",
201
239
  "fieldName": "indeterminate"
202
240
  },
203
241
  {
@@ -209,6 +247,10 @@
209
247
  }
210
248
  ],
211
249
  "mixins": [
250
+ {
251
+ "name": "FormControlMixin",
252
+ "package": "@justeattakeaway/pie-webc-core"
253
+ },
212
254
  {
213
255
  "name": "RtlMixin",
214
256
  "package": "@justeattakeaway/pie-webc-core"
package/dist/index.d.ts CHANGED
@@ -1,6 +1,9 @@
1
+ import { ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
1
2
  import type { CSSResult } from 'lit';
3
+ import type { FormControlInterface } from '@justeattakeaway/pie-webc-core';
2
4
  import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
3
5
  import type { LitElement } from 'lit';
6
+ import type { PropertyValues } from 'lit';
4
7
  import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
5
8
  import type { TemplateResult } from 'lit-html';
6
9
 
@@ -28,7 +31,7 @@ export declare interface CheckboxProps {
28
31
  */
29
32
  disabled?: boolean;
30
33
  /**
31
- * 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.
32
35
  */
33
36
  checked?: boolean;
34
37
  /**
@@ -46,9 +49,13 @@ export declare interface CheckboxProps {
46
49
  aria?: AriaProps;
47
50
  }
48
51
 
52
+ export declare type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'value' | 'required' | 'indeterminate' | 'checked'>;
53
+
54
+ export declare const defaultProps: DefaultProps;
55
+
49
56
  /**
50
57
  * @tagname pie-checkbox
51
- * @slot - Default slot (checkbox label)
58
+ * @event {CustomEvent} change - when checked state is changed.
52
59
  */
53
60
  export declare class PieCheckbox extends PieCheckbox_base implements CheckboxProps {
54
61
  static shadowRootOptions: {
@@ -56,10 +63,10 @@ export declare class PieCheckbox extends PieCheckbox_base implements CheckboxPro
56
63
  mode: ShadowRootMode;
57
64
  slotAssignment?: SlotAssignmentMode | undefined;
58
65
  };
59
- value: CheckboxProps['value'];
66
+ value: string;
60
67
  label?: CheckboxProps['label'];
61
68
  name?: CheckboxProps['name'];
62
- checked?: CheckboxProps['checked'];
69
+ checked: boolean;
63
70
  disabled?: CheckboxProps['disabled'];
64
71
  required?: CheckboxProps['required'];
65
72
  indeterminate?: CheckboxProps['indeterminate'];
@@ -71,7 +78,20 @@ export declare class PieCheckbox extends PieCheckbox_base implements CheckboxPro
71
78
  */
72
79
  get validity(): ValidityState;
73
80
  /**
74
- * 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.
75
95
  * @param {Event} event - This should be the change event that was listened for on an input element with `type="checkbox"`.
76
96
  */
77
97
  private handleChange;
@@ -79,6 +99,6 @@ export declare class PieCheckbox extends PieCheckbox_base implements CheckboxPro
79
99
  static styles: CSSResult;
80
100
  }
81
101
 
82
- declare const PieCheckbox_base: GenericConstructor<RTLInterface> & typeof LitElement;
102
+ declare const PieCheckbox_base: GenericConstructor<FormControlInterface> & GenericConstructor<RTLInterface> & typeof LitElement;
83
103
 
84
104
  export { }
package/dist/index.js CHANGED
@@ -1,21 +1,26 @@
1
- import { LitElement as b, html as u, nothing as c, unsafeCSS as m } from "lit";
2
- import { RtlMixin as f, wrapNativeEvent as v, defineCustomElement as g } from "@justeattakeaway/pie-webc-core";
3
- import { property as i, query as $ } from "lit/decorators.js";
4
- import { ifDefined as h } from "lit/directives/if-defined.js";
5
- const x = `*,*:after,*:before{box-sizing:inherit}
6
- `;
7
- var C = Object.defineProperty, O = Object.getOwnPropertyDescriptor, r = (d, n, p, l) => {
8
- for (var t = l > 1 ? void 0 : l ? O(n, p) : n, a = d.length - 1, s; a >= 0; a--)
9
- (s = d[a]) && (t = (l ? s(n, p, t) : s(t)) || t);
10
- return l && t && C(n, p, t), t;
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",
11
+ required: !1,
12
+ indeterminate: !1,
13
+ checked: !1
11
14
  };
12
- const S = "pie-checkbox";
13
- class e extends f(b) {
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;
19
+ };
20
+ const O = "pie-checkbox";
21
+ class t extends y(v(u)) {
14
22
  constructor() {
15
- super(...arguments), this.required = !1, this.indeterminate = !1, this.handleChange = (n) => {
16
- const p = v(n);
17
- this.dispatchEvent(p);
18
- };
23
+ super(...arguments), this.value = p.value, this.checked = p.checked, this.required = p.required, this.indeterminate = p.indeterminate;
19
24
  }
20
25
  /**
21
26
  * (Read-only) returns a ValidityState with the validity states that this element is in.
@@ -24,67 +29,99 @@ class e extends f(b) {
24
29
  get validity() {
25
30
  return this.checkbox.validity;
26
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
+ }
27
63
  render() {
28
64
  const {
29
- checked: n,
30
- value: p,
31
- name: l,
32
- label: t,
33
- disabled: a,
34
- required: s,
35
- indeterminate: y,
36
- aria: o
65
+ checked: e,
66
+ value: n,
67
+ name: s,
68
+ label: o,
69
+ disabled: l,
70
+ required: c,
71
+ indeterminate: m,
72
+ aria: r
37
73
  } = this;
38
- return u`
39
- <label>
74
+ return b`
75
+ <label data-test-id="checkbox-component">
40
76
  <input
41
77
  type="checkbox"
42
- ?checked=${h(n)}
43
- .value=${h(p)}
44
- name=${h(l)}
45
- ?disabled=${a}
46
- ?required=${s}
47
- .indeterminate=${y}
48
- aria-label=${(o == null ? void 0 : o.label) || c}
49
- aria-labelledby=${t ? c : (o == null ? void 0 : o.labelledby) || c}
50
- aria-describedby= ${(o == null ? void 0 : o.describedby) || c}
78
+ .value=${n}
79
+ ?checked=${x(e)}
80
+ name=${C(s)}
81
+ ?disabled=${l}
82
+ ?required=${c}
83
+ .indeterminate=${m}
84
+ aria-label=${(r == null ? void 0 : r.label) || d}
85
+ aria-labelledby=${o ? d : (r == null ? void 0 : r.labelledby) || d}
86
+ aria-describedby= ${(r == null ? void 0 : r.describedby) || d}
51
87
  @change=${this.handleChange}
52
- data-test-id="pie-checkbox"
88
+ data-test-id="checkbox-input"
53
89
  />
54
- ${t}
90
+ ${o}
55
91
  </label>`;
56
92
  }
57
93
  }
58
- e.shadowRootOptions = { ...b.shadowRootOptions, delegatesFocus: !0 };
59
- e.styles = m(x);
60
- r([
61
- i({ type: String })
62
- ], e.prototype, "value", 2);
63
- r([
64
- i({ type: String })
65
- ], e.prototype, "label", 2);
66
- r([
67
- i({ type: String })
68
- ], e.prototype, "name", 2);
69
- r([
70
- i({ type: Boolean })
71
- ], e.prototype, "checked", 2);
72
- r([
73
- i({ type: Boolean, reflect: !0 })
74
- ], e.prototype, "disabled", 2);
75
- r([
76
- i({ type: Boolean, reflect: !0 })
77
- ], e.prototype, "required", 2);
78
- r([
79
- i({ type: Boolean })
80
- ], e.prototype, "indeterminate", 2);
81
- r([
82
- i({ type: Object })
83
- ], e.prototype, "aria", 2);
84
- r([
85
- $("input")
86
- ], e.prototype, "checkbox", 2);
87
- g(S, 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);
88
124
  export {
89
- e as PieCheckbox
125
+ t as PieCheckbox,
126
+ p as defaultProps
90
127
  };
package/dist/react.d.ts CHANGED
@@ -1,6 +1,9 @@
1
+ import { ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
1
2
  import type { CSSResult } from 'lit';
3
+ import type { FormControlInterface } from '@justeattakeaway/pie-webc-core';
2
4
  import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
3
5
  import type { LitElement } from 'lit';
6
+ import type { PropertyValues } from 'lit';
4
7
  import * as React_2 from 'react';
5
8
  import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
6
9
  import type { TemplateResult } from 'lit-html';
@@ -29,7 +32,7 @@ export declare interface CheckboxProps {
29
32
  */
30
33
  disabled?: boolean;
31
34
  /**
32
- * 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.
33
36
  */
34
37
  checked?: boolean;
35
38
  /**
@@ -47,11 +50,15 @@ export declare interface CheckboxProps {
47
50
  aria?: AriaProps;
48
51
  }
49
52
 
50
- export declare const PieCheckbox: React_2.ForwardRefExoticComponent<CheckboxProps & React_2.RefAttributes<PieCheckbox_2> & ReactBaseType>;
53
+ export declare type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'value' | 'required' | 'indeterminate' | 'checked'>;
54
+
55
+ export declare const defaultProps: DefaultProps;
56
+
57
+ export declare const PieCheckbox: React_2.ForwardRefExoticComponent<CheckboxProps & React_2.RefAttributes<PieCheckbox_2> & PieCheckboxEvents & ReactBaseType>;
51
58
 
52
59
  /**
53
60
  * @tagname pie-checkbox
54
- * @slot - Default slot (checkbox label)
61
+ * @event {CustomEvent} change - when checked state is changed.
55
62
  */
56
63
  declare class PieCheckbox_2 extends PieCheckbox_base implements CheckboxProps {
57
64
  static shadowRootOptions: {
@@ -59,10 +66,10 @@ declare class PieCheckbox_2 extends PieCheckbox_base implements CheckboxProps {
59
66
  mode: ShadowRootMode;
60
67
  slotAssignment?: SlotAssignmentMode | undefined;
61
68
  };
62
- value: CheckboxProps['value'];
69
+ value: string;
63
70
  label?: CheckboxProps['label'];
64
71
  name?: CheckboxProps['name'];
65
- checked?: CheckboxProps['checked'];
72
+ checked: boolean;
66
73
  disabled?: CheckboxProps['disabled'];
67
74
  required?: CheckboxProps['required'];
68
75
  indeterminate?: CheckboxProps['indeterminate'];
@@ -74,7 +81,20 @@ declare class PieCheckbox_2 extends PieCheckbox_base implements CheckboxProps {
74
81
  */
75
82
  get validity(): ValidityState;
76
83
  /**
77
- * 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.
78
98
  * @param {Event} event - This should be the change event that was listened for on an input element with `type="checkbox"`.
79
99
  */
80
100
  private handleChange;
@@ -82,8 +102,12 @@ declare class PieCheckbox_2 extends PieCheckbox_base implements CheckboxProps {
82
102
  static styles: CSSResult;
83
103
  }
84
104
 
85
- 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
+ };
86
110
 
87
- declare type ReactBaseType = React_2.HTMLAttributes<HTMLElement>;
111
+ declare type ReactBaseType = React_2.InputHTMLAttributes<HTMLInputElement>;
88
112
 
89
113
  export { }
package/dist/react.js CHANGED
@@ -1,17 +1,23 @@
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 b } from "./index.js";
4
5
  import "lit";
5
6
  import "@justeattakeaway/pie-webc-core";
7
+ import "lit/directives/live.js";
6
8
  import "lit/decorators.js";
7
9
  import "lit/directives/if-defined.js";
8
- const i = o({
10
+ const r = o({
9
11
  displayName: "PieCheckbox",
10
12
  elementClass: t,
11
13
  react: e,
12
14
  tagName: "pie-checkbox",
13
- events: {}
14
- }), x = i;
15
+ events: {
16
+ onChange: "change"
17
+ // when checked state is changed.
18
+ }
19
+ }), h = r;
15
20
  export {
16
- x as PieCheckbox
21
+ h as PieCheckbox,
22
+ b as defaultProps
17
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.0",
4
+ "version": "0.4.0",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -40,7 +40,7 @@
40
40
  "cem-plugin-module-file-extensions": "0.0.5"
41
41
  },
42
42
  "dependencies": {
43
- "@justeattakeaway/pie-webc-core": "0.22.0"
43
+ "@justeattakeaway/pie-webc-core": "0.23.0"
44
44
  },
45
45
  "volta": {
46
46
  "extends": "../../../package.json"
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
@@ -1,3 +1,5 @@
1
+ import { type ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
2
+
1
3
  export type AriaProps = {
2
4
  label?: string;
3
5
  labelledby?: string;
@@ -25,7 +27,7 @@ export interface CheckboxProps {
25
27
  disabled?: boolean;
26
28
 
27
29
  /**
28
- * 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.
29
31
  */
30
32
  checked?: boolean;
31
33
 
@@ -45,3 +47,15 @@ export interface CheckboxProps {
45
47
  */
46
48
  aria?: AriaProps;
47
49
  }
50
+
51
+ export type DefaultProps = ComponentDefaultPropsGeneric<CheckboxProps, 'value' | 'required' | 'indeterminate' | 'checked' >;
52
+
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',
57
+ required: false,
58
+ indeterminate: false,
59
+ checked: false,
60
+ };
61
+
package/src/index.ts CHANGED
@@ -1,16 +1,18 @@
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
 
12
14
  import styles from './checkbox.scss?inline';
13
- import { CheckboxProps } from './defs';
15
+ import { CheckboxProps, defaultProps } from './defs';
14
16
 
15
17
  // Valid values available to consumers
16
18
  export * from './defs';
@@ -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,22 +35,22 @@ 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'];
41
43
 
42
44
  @property({ type: Boolean, reflect: true })
43
- public required?: CheckboxProps['required'] = false;
45
+ public required?: CheckboxProps['required'] = defaultProps.required;
44
46
 
45
- @property({ type: Boolean })
46
- public indeterminate?: CheckboxProps['indeterminate'] = false;
47
+ @property({ type: Boolean, reflect: true })
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>;