@justeattakeaway/pie-button 0.18.0 → 0.19.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.
@@ -1,14 +1,14 @@
1
- [13:50:20] @custom-elements-manifest/analyzer: Created new manifest.
1
+ [1:45:52 PM] @custom-elements-manifest/analyzer: Created new manifest.
2
2
  react wrapper has been added!
3
3
  vite v4.3.9 building for production...
4
4
  transforming...
5
5
  ✓ 22 modules transformed.
6
6
  rendering chunks...
7
7
  computing gzip size...
8
- dist/index.js  8.26 kB │ gzip: 1.86 kB
8
+ dist/index.js 11.55 kB │ gzip: 2.37 kB
9
9
  dist/react.js 59.01 kB │ gzip: 15.91 kB
10
-
11
- [vite:dts] Start generate declaration files...
12
- ✓ built in 4.60s
13
- [vite:dts] Declaration files built in 4021ms.
14
-
10
+ 
11
+ [vite:dts] Start generate declaration files...
12
+ ✓ built in 10.50s
13
+ [vite:dts] Declaration files built in 9519ms.
14
+ 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.19.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [Added] - pie-button loading state ([#603](https://github.com/justeattakeaway/pie/pull/603)) by [@jamieomaguire](https://github.com/jamieomaguire)
8
+
3
9
  ## 0.18.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -72,6 +72,7 @@ import { PieButton } from '@justeattakeaway/pie-button/dist/react';
72
72
  | variant | `String` | `primary` | Variant of the button, one of `variants` – `primary`, `secondary`, `outline`, `ghost`, `inverse`, `ghost-inverse` |
73
73
  | disabled | `Boolean` | `false` | If `true`, disables the button. |
74
74
  | isFullWidth | `Boolean` | `false` | If `true`, sets the button width to 100% of it's container. |
75
+ | isLoading | `Boolean` | `false` | If `true`, displays a loading indicator inside the button.
75
76
 
76
77
  In your markup or JSX, you can then use these to set the properties for the `pie-button` component:
77
78
 
package/dist/index.js CHANGED
@@ -1,75 +1,84 @@
1
- import { unsafeCSS as h, LitElement as u, html as g } from "lit";
2
- import { property as l } from "lit/decorators.js";
1
+ import { unsafeCSS as h, LitElement as u, html as m } from "lit";
2
+ import { property as c } from "lit/decorators.js";
3
3
  import "lit/decorators/property.js";
4
- const b = (c, o, e) => function(t, r) {
5
- const a = `#${r}`;
6
- Object.defineProperty(t, r, {
4
+ const b = (l, r, t) => function(o, e) {
5
+ const n = `#${e}`;
6
+ Object.defineProperty(o, e, {
7
7
  get() {
8
- return this[a];
8
+ return this[n];
9
9
  },
10
10
  set(v) {
11
- const p = this[a];
12
- o.includes(v) ? this[a] = v : (console.error(
13
- `<${c}> Invalid value "${v}" provided for property "${r}".`,
14
- `Must be one of: ${o.join(" | ")}.`,
15
- `Falling back to default value: "${e}"`
16
- ), this[a] = e), this.requestUpdate(r, p);
11
+ const p = this[n];
12
+ r.includes(v) ? this[n] = v : (console.error(
13
+ `<${l}> Invalid value "${v}" provided for property "${e}".`,
14
+ `Must be one of: ${r.join(" | ")}.`,
15
+ `Falling back to default value: "${t}"`
16
+ ), this[n] = t), this.requestUpdate(e, p);
17
17
  }
18
18
  });
19
- }, m = `.o-btn{--btn-border-radius: var(--dt-radius-rounded-e);--btn-font-family: var(--dt-font-interactive-m-family);--btn-font-weight: var(--dt-font-interactive-m-weight);--btn-padding: 10px var(--dt-spacing-e);--btn-min-height: 48px;--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);--btn-bg-color: var(--dt-color-interactive-brand);--btn-text-color: var(--dt-color-content-interactive-primary);min-block-size:var(--btn-min-block-size);padding:var(--btn-padding);border:none;border-radius:var(--btn-border-radius);outline:none;background-color:var(--btn-bg-color);font-family:var(--btn-font-family);font-size:var(--btn-font-size);font-weight:var(--btn-font-weight);color:var(--btn-text-color);line-height:var(--btn-line-height);cursor:pointer;user-select:none}.o-btn:focus-visible{box-shadow:0 0 0 2px var(--dt-color-focus-inner);outline:none;position:relative}.o-btn:focus-visible:after{content:"";display:block;position:absolute;top:-3px;left:-3px;right:-3px;bottom:-3px;border-radius:var(--btn-border-radius);box-shadow:0 0 0 2px var(--dt-color-focus-outer)}.o-btn[variant=primary]:hover:not(:disabled){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)))}.o-btn[variant=primary]:active:not(:disabled){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)))}.o-btn[variant=primary][size=xsmall],.o-btn[variant=primary][size=small-productive]{--btn-bg-color: var(--dt-color-interactive-primary)}.o-btn[variant=primary][size=xsmall]:hover:not(:disabled),.o-btn[variant=primary][size=small-productive]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-primary-h),var(--dt-color-interactive-primary-s),calc(var(--dt-color-interactive-primary-l) - var(--dt-color-hover-01)))}.o-btn[variant=primary][size=xsmall]:active:not(:disabled),.o-btn[variant=primary][size=small-productive]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-primary-h),var(--dt-color-interactive-primary-s),calc(var(--dt-color-interactive-primary-l) - var(--dt-color-active-01)))}.o-btn[variant=secondary]{--btn-bg-color: var(--dt-color-interactive-secondary);--btn-text-color: var(--dt-color-content-interactive-secondary)}.o-btn[variant=secondary]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-secondary-h),var(--dt-color-interactive-secondary-s),calc(var(--dt-color-interactive-secondary-l) - var(--dt-color-hover-01)))}.o-btn[variant=secondary]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-secondary-h),var(--dt-color-interactive-secondary-s),calc(var(--dt-color-interactive-secondary-l) - var(--dt-color-active-01)))}.o-btn[variant=outline]{--btn-bg-color: var(--dt-color-container-default);--btn-text-color: var(--dt-color-content-interactive-secondary);border:1px solid var(--dt-color-border-strong)}.o-btn[variant=outline]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}.o-btn[variant=outline]:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}.o-btn[variant=ghost]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-link)}.o-btn[variant=ghost]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}.o-btn[variant=ghost]:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}.o-btn[variant=inverse]{--btn-bg-color: var(--dt-color-interactive-inverse);--btn-text-color: var(--dt-color-content-interactive-secondary)}.o-btn[variant=inverse]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-inverse-h),var(--dt-color-interactive-inverse-s),calc(var(--dt-color-interactive-inverse-l) - var(--dt-color-hover-01)))}.o-btn[variant=inverse]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-inverse-h),var(--dt-color-interactive-inverse-s),calc(var(--dt-color-interactive-inverse-l) - var(--dt-color-active-01)))}.o-btn[variant=ghost-inverse]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-primary)}.o-btn[variant=ghost-inverse]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-inverse-h),var(--dt-color-container-inverse-s),calc(var(--dt-color-container-inverse-l) - var(--dt-color-hover-01)))}.o-btn[variant=ghost-inverse]:active:not(:disabled){background-color:hsl(var(--dt-color-container-inverse-h),var(--dt-color-container-inverse-s),calc(var(--dt-color-container-inverse-l) - var(--dt-color-active-01)))}.o-btn[isFullWidth]{inline-size:100%}.o-btn[disabled]{--btn-text-color: var(--dt-color-content-disabled) !important;cursor:not-allowed}.o-btn[disabled]:not([variant=ghost],[variant=ghost-inverse]){--btn-bg-color: var(--dt-color-disabled-01) !important}.o-btn[disabled][variant=outline]{border-color:var(--dt-color-disabled-01)!important}.o-btn[size=xsmall]{--btn-padding: 6px var(--dt-spacing-b);--btn-font-size: calc(var(--dt-font-size-14) * 1px);--btn-line-height: calc(var(--dt-font-size-14-line-height) * 1px)}.o-btn[size=small-expressive]{--btn-padding: 6px var(--dt-spacing-d);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px)}.o-btn[size=small-productive]{--btn-padding: 8px var(--dt-spacing-d);--btn-font-size: calc(var(--dt-font-size-16) * 1px);--btn-line-height: calc(var(--dt-font-size-16-line-height) * 1px)}.o-btn[size=large]{--btn-padding: 14px var(--dt-spacing-e);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px)}
19
+ }, g = `*,*:before,*:after{box-sizing:border-box}@keyframes rotate360{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.o-btn{--btn-border-radius: var(--dt-radius-rounded-e);--btn-font-family: var(--dt-font-interactive-m-family);--btn-font-weight: var(--dt-font-interactive-m-weight);--btn-padding: 10px var(--dt-spacing-e);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);--btn-bg-color: var(--dt-color-interactive-brand);--btn-text-color: var(--dt-color-content-interactive-primary);--spinner-size-s: 20px;--spinner-size-m: 24px;--spinner-border-width-s: 2.5px;--spinner-border-width-m: 3px;--spinner-size: var(--spinner-size-m);--spinner-border-width: var(--spinner-border-width-m);--spinner-base-color-h: var(--dt-color-content-interactive-primary-h);--spinner-base-color-s: var(--dt-color-content-interactive-primary-s);--spinner-base-color-l: var(--dt-color-content-interactive-primary-l);--spinner-left-color-opacity: .35;--spinner-left-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), var(--spinner-left-color-opacity));--spinner-right-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), 1);--spinner-animation-duration: 1.15s;--spinner-animation-timing-function: linear;--spinner-animation-iteration-count: infinite;position:relative;box-sizing:border-box;padding:var(--btn-padding);border:none;border-radius:var(--btn-border-radius);outline:none;background-color:var(--btn-bg-color);font-family:var(--btn-font-family);font-size:var(--btn-font-size);font-weight:var(--btn-font-weight);color:var(--btn-text-color);line-height:var(--btn-line-height);cursor:pointer;user-select:none}.o-btn:focus-visible{box-shadow:0 0 0 2px var(--dt-color-focus-inner);outline:none;position:relative}.o-btn:focus-visible:after{content:"";display:block;position:absolute;top:-3px;left:-3px;right:-3px;bottom:-3px;border-radius:var(--btn-border-radius);box-shadow:0 0 0 2px var(--dt-color-focus-outer)}.o-btn[variant=primary]:hover:not(:disabled){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)))}.o-btn[variant=primary]:active:not(:disabled){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)))}.o-btn[variant=primary][size=xsmall],.o-btn[variant=primary][size=small-productive]{--btn-bg-color: var(--dt-color-interactive-primary)}.o-btn[variant=primary][size=xsmall]:hover:not(:disabled),.o-btn[variant=primary][size=small-productive]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-primary-h),var(--dt-color-interactive-primary-s),calc(var(--dt-color-interactive-primary-l) - var(--dt-color-hover-01)))}.o-btn[variant=primary][size=xsmall]:active:not(:disabled),.o-btn[variant=primary][size=small-productive]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-primary-h),var(--dt-color-interactive-primary-s),calc(var(--dt-color-interactive-primary-l) - var(--dt-color-active-01)))}.o-btn[variant=secondary]{--btn-bg-color: var(--dt-color-interactive-secondary);--btn-text-color: var(--dt-color-content-interactive-secondary);--spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);--spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);--spinner-base-color-l: var(--dt-color-content-interactive-secondary-l)}.o-btn[variant=secondary]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-secondary-h),var(--dt-color-interactive-secondary-s),calc(var(--dt-color-interactive-secondary-l) - var(--dt-color-hover-01)))}.o-btn[variant=secondary]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-secondary-h),var(--dt-color-interactive-secondary-s),calc(var(--dt-color-interactive-secondary-l) - var(--dt-color-active-01)))}.o-btn[variant=outline]{--btn-bg-color: var(--dt-color-container-default);--btn-text-color: var(--dt-color-content-interactive-secondary);--spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);--spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);--spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);border:1px solid var(--dt-color-border-strong)}.o-btn[variant=outline]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}.o-btn[variant=outline]:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}.o-btn[variant=ghost]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-link);--spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);--spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);--spinner-base-color-l: var(--dt-color-content-interactive-secondary-l)}.o-btn[variant=ghost]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-hover-01)))}.o-btn[variant=ghost]:active:not(:disabled){background-color:hsl(var(--dt-color-container-default-h),var(--dt-color-container-default-s),calc(var(--dt-color-container-default-l) - var(--dt-color-active-01)))}.o-btn[variant=inverse]{--btn-bg-color: var(--dt-color-interactive-inverse);--btn-text-color: var(--dt-color-content-interactive-secondary);--spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);--spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);--spinner-base-color-l: var(--dt-color-content-interactive-secondary-l)}.o-btn[variant=inverse]:hover:not(:disabled){background-color:hsl(var(--dt-color-interactive-inverse-h),var(--dt-color-interactive-inverse-s),calc(var(--dt-color-interactive-inverse-l) - var(--dt-color-hover-01)))}.o-btn[variant=inverse]:active:not(:disabled){background-color:hsl(var(--dt-color-interactive-inverse-h),var(--dt-color-interactive-inverse-s),calc(var(--dt-color-interactive-inverse-l) - var(--dt-color-active-01)))}.o-btn[variant=ghost-inverse]{--btn-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-primary);--spinner-base-color-h: var(--dt-color-content-interactive-primary-h);--spinner-base-color-s: var(--dt-color-content-interactive-primary-s);--spinner-base-color-l: var(--dt-color-content-interactive-primary-l)}.o-btn[variant=ghost-inverse]:hover:not(:disabled){background-color:hsl(var(--dt-color-container-inverse-h),var(--dt-color-container-inverse-s),calc(var(--dt-color-container-inverse-l) - var(--dt-color-hover-01)))}.o-btn[variant=ghost-inverse]:active:not(:disabled){background-color:hsl(var(--dt-color-container-inverse-h),var(--dt-color-container-inverse-s),calc(var(--dt-color-container-inverse-l) - var(--dt-color-active-01)))}.o-btn[isFullWidth]{inline-size:100%}.o-btn[disabled]{--btn-text-color: var(--dt-color-content-disabled) !important;cursor:not-allowed}.o-btn[disabled]:not([variant=ghost],[variant=ghost-inverse]){--btn-bg-color: var(--dt-color-disabled-01) !important}.o-btn[disabled][variant=outline]{border-color:var(--dt-color-disabled-01)!important}.o-btn[size=xsmall]{--btn-padding: 6px var(--dt-spacing-b);--btn-font-size: calc(var(--dt-font-size-14) * 1px);--btn-line-height: calc(var(--dt-font-size-14-line-height) * 1px);--spinner-size: var(--spinner-size-s);--spinner-border-width: var(--spinner-border-width-s)}.o-btn[size=small-expressive]{--btn-padding: 6px var(--dt-spacing-d);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);--spinner-size: var(--spinner-size-s);--spinner-border-width: var(--spinner-border-width-s)}.o-btn[size=small-productive]{--btn-padding: 8px var(--dt-spacing-d);--btn-font-size: calc(var(--dt-font-size-16) * 1px);--btn-line-height: calc(var(--dt-font-size-16-line-height) * 1px);--spinner-size: var(--spinner-size-s);--spinner-border-width: var(--spinner-border-width-s)}.o-btn[size=large]{--btn-padding: 14px var(--dt-spacing-e);--btn-font-size: calc(var(--dt-font-size-20) * 1px);--btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);--spinner-size: var(--spinner-size-m);--spinner-border-width: var(--spinner-border-width-m)}.o-btn:before{content:"";position:absolute;left:50%;top:50%;translate:-50% -50%;height:var(--spinner-size);width:var(--spinner-size);display:block;background-color:transparent;border-radius:50%;border-color:var(--spinner-left-color) var(--spinner-right-color) var(--spinner-right-color) var(--spinner-left-color);border-width:var(--spinner-border-width);border-style:solid;will-change:transform;opacity:0}.o-btn[isLoading]:before{animation:rotate360 var(--spinner-animation-duration) var(--spinner-animation-timing-function) var(--spinner-animation-iteration-count);opacity:1}.o-btn[isLoading] .o-btn-text{opacity:0}
20
20
  `, f = ["xsmall", "small-productive", "small-expressive", "medium", "large"], y = ["submit", "button", "reset", "menu"], x = ["primary", "secondary", "outline", "ghost", "inverse", "ghost-inverse"];
21
- var z = Object.defineProperty, k = Object.getOwnPropertyDescriptor, d = (c, o, e, n) => {
22
- for (var t = n > 1 ? void 0 : n ? k(o, e) : o, r = c.length - 1, a; r >= 0; r--)
23
- (a = c[r]) && (t = (n ? a(o, e, t) : a(t)) || t);
24
- return n && t && z(o, e, t), t;
21
+ var z = Object.defineProperty, w = Object.getOwnPropertyDescriptor, s = (l, r, t, i) => {
22
+ for (var o = i > 1 ? void 0 : i ? w(r, t) : r, e = l.length - 1, n; e >= 0; e--)
23
+ (n = l[e]) && (o = (i ? n(r, t, o) : n(o)) || o);
24
+ return i && o && z(r, t, o), o;
25
25
  };
26
- const s = "pie-button";
27
- class i extends u {
26
+ const d = "pie-button";
27
+ class a extends u {
28
28
  constructor() {
29
- super(...arguments), this.size = "medium", this.type = "submit", this.variant = "primary", this.disabled = !1, this.isFullWidth = !1;
29
+ super(...arguments), this.size = "medium", this.type = "submit", this.variant = "primary", this.disabled = !1, this.isLoading = !1, this.isFullWidth = !1;
30
30
  }
31
31
  render() {
32
32
  const {
33
- type: o,
34
- disabled: e,
35
- isFullWidth: n,
36
- variant: t,
37
- size: r
33
+ type: r,
34
+ disabled: t,
35
+ isFullWidth: i,
36
+ variant: o,
37
+ size: e,
38
+ isLoading: n
38
39
  } = this;
39
- return g`
40
+ return m`
40
41
  <button
41
42
  class="o-btn"
42
- type=${o}
43
- variant=${t}
44
- size=${r}
45
- ?disabled=${e}
46
- ?isFullWidth=${n}>
47
- <slot></slot>
43
+ type=${r}
44
+ variant=${o}
45
+ size=${e}
46
+ ?disabled=${t}
47
+ ?isFullWidth=${i}
48
+ ?isLoading=${n}>
49
+ <span class="o-btn-text"><slot></slot></span>
48
50
  </button>`;
49
51
  }
52
+ focus() {
53
+ var r, t;
54
+ (t = (r = this.shadowRoot) == null ? void 0 : r.querySelector("button")) == null || t.focus();
55
+ }
50
56
  }
51
- i.styles = h(m);
52
- d([
53
- l(),
54
- b(s, f, "medium")
55
- ], i.prototype, "size", 2);
56
- d([
57
- l(),
58
- b(s, y, "submit")
59
- ], i.prototype, "type", 2);
60
- d([
61
- l(),
62
- b(s, x, "primary")
63
- ], i.prototype, "variant", 2);
64
- d([
65
- l({ type: Boolean })
66
- ], i.prototype, "disabled", 2);
67
- d([
68
- l({ type: Boolean })
69
- ], i.prototype, "isFullWidth", 2);
70
- customElements.define(s, i);
57
+ a.styles = h(g);
58
+ s([
59
+ c(),
60
+ b(d, f, "medium")
61
+ ], a.prototype, "size", 2);
62
+ s([
63
+ c(),
64
+ b(d, y, "submit")
65
+ ], a.prototype, "type", 2);
66
+ s([
67
+ c(),
68
+ b(d, x, "primary")
69
+ ], a.prototype, "variant", 2);
70
+ s([
71
+ c({ type: Boolean })
72
+ ], a.prototype, "disabled", 2);
73
+ s([
74
+ c({ type: Boolean, reflect: !0 })
75
+ ], a.prototype, "isLoading", 2);
76
+ s([
77
+ c({ type: Boolean })
78
+ ], a.prototype, "isFullWidth", 2);
79
+ customElements.define(d, a);
71
80
  export {
72
- i as PieButton,
81
+ a as PieButton,
73
82
  f as sizes,
74
83
  y as types,
75
84
  x as variants
package/dist/react.js CHANGED
File without changes
File without changes
@@ -3,29 +3,28 @@ export declare const types: readonly ["submit", "button", "reset", "menu"];
3
3
  export declare const variants: readonly ["primary", "secondary", "outline", "ghost", "inverse", "ghost-inverse"];
4
4
  export interface ButtonProps {
5
5
  /**
6
- * (Optional) What size the button should be.
7
- * @default "medium"
6
+ * What size the button should be.
8
7
  */
9
8
  size: typeof sizes[number];
10
9
  /**
11
- * (Optional) What type attribute should be applied to the button. For example submit, button or menu.
12
- * @default "submit"
10
+ * What type attribute should be applied to the button. For example submit, button or menu.
13
11
  */
14
12
  type: typeof types[number];
15
13
  /**
16
- * (Optional) What style variant the button should be such as primary, outline or ghost.
17
- * @default "primary"
14
+ * What style variant the button should be such as primary, outline or ghost.
18
15
  */
19
16
  variant: typeof variants[number];
20
17
  /**
21
- * (Optional) When true, the button element is disabled.
22
- * @default false
18
+ * When true, the button element is disabled.
23
19
  */
24
20
  disabled: boolean;
25
21
  /**
26
- * (Optional) When true, the button element will occupy the full width of its container.
27
- * @default false
22
+ * When true, the button element will occupy the full width of its container.
28
23
  */
29
24
  isFullWidth: boolean;
25
+ /**
26
+ * When true, displays a loading indicator inside the button.
27
+ */
28
+ isLoading: boolean;
30
29
  }
31
30
  //# sourceMappingURL=defs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,gFAAiF,CAAC;AACpG,eAAO,MAAM,KAAK,gDAAiD,CAAC;AACpE,eAAO,MAAM,QAAQ,mFAAoF,CAAC;AAE1G,MAAM,WAAW,WAAW;IACxB;;;OAGG;IACH,IAAI,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B;;;OAGG;IACH,IAAI,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B;;;OAGG;IACH,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,WAAW,EAAE,OAAO,CAAC;CACxB"}
1
+ {"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,gFAAiF,CAAC;AACpG,eAAO,MAAM,KAAK,gDAAiD,CAAC;AACpE,eAAO,MAAM,QAAQ,mFAAoF,CAAC;AAE1G,MAAM,WAAW,WAAW;IACxB;;OAEG;IACH,IAAI,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B;;OAEG;IACH,IAAI,EAAE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B;;OAEG;IACH,OAAO,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACtB"}
@@ -2,13 +2,15 @@ import { LitElement } from 'lit';
2
2
  import { ButtonProps, sizes, types, variants } from './defs';
3
3
  export { type ButtonProps, sizes, types, variants, };
4
4
  declare const componentSelector = "pie-button";
5
- export declare class PieButton extends LitElement {
5
+ export declare class PieButton extends LitElement implements ButtonProps {
6
6
  size: ButtonProps['size'];
7
7
  type: ButtonProps['type'];
8
8
  variant: ButtonProps['variant'];
9
9
  disabled: boolean;
10
+ isLoading: boolean;
10
11
  isFullWidth: boolean;
11
12
  render(): import("lit-html").TemplateResult<1>;
13
+ focus(): void;
12
14
  static styles: import("lit").CSSResult;
13
15
  }
14
16
  declare global {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,KAAK,CAAC;AAIlD,OAAO,EACH,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EACtC,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,EACL,KAAK,EACL,QAAQ,GACX,CAAC;AAEF,QAAA,MAAM,iBAAiB,eAAe,CAAC;AAEvC,qBAAa,SAAU,SAAQ,UAAU;IAG9B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAY;IAIrC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAY;IAIrC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAa;IAG5C,QAAQ,UAAS;IAGjB,WAAW,UAAS;IAE3B,MAAM;IAkBN,MAAM,CAAC,MAAM,0BAAqB;CACrC;AAID,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;KAClC;CACJ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmB,MAAM,KAAK,CAAC;AAIlD,OAAO,EACH,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EACtC,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACH,KAAK,WAAW,EAChB,KAAK,EACL,KAAK,EACL,QAAQ,GACX,CAAC;AAEF,QAAA,MAAM,iBAAiB,eAAe,CAAC;AAEvC,qBAAa,SAAU,SAAQ,UAAW,YAAW,WAAW;IAGrD,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAY;IAIrC,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAY;IAIrC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAa;IAG5C,QAAQ,UAAS;IAGjB,SAAS,UAAS;IAGlB,WAAW,UAAS;IAE3B,MAAM;IAkBN,KAAK;IAKL,MAAM,CAAC,MAAM,0BAAqB;CACrC;AAID,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;KAClC;CACJ"}
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-button",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "description": "PIE design system button built using web components",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/button.scss CHANGED
@@ -1,3 +1,9 @@
1
+ *,
2
+ *:before,
3
+ *:after {
4
+ box-sizing: border-box;
5
+ }
6
+
1
7
  // Defines button interactive states for hover and active using HSL & calc
2
8
  // Takes a color token name as an argument
3
9
  @mixin button-interactive-states($bg-color) {
@@ -10,6 +16,17 @@
10
16
  }
11
17
  }
12
18
 
19
+ // Spin animation for loading state
20
+ @keyframes rotate360 {
21
+ from {
22
+ transform: rotate(0deg);
23
+ }
24
+
25
+ to {
26
+ transform: rotate(360deg);
27
+ }
28
+ }
29
+
13
30
  // Base button styles
14
31
  .o-btn {
15
32
  // Custom Property Declarations
@@ -20,7 +37,6 @@
20
37
 
21
38
  // The base values are set to the size default, which is for the medium button size
22
39
  --btn-padding: 10px var(--dt-spacing-e);
23
- --btn-min-height: 48px;
24
40
  --btn-font-size: calc(var(--dt-font-size-20) * 1px);
25
41
  --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);
26
42
 
@@ -29,7 +45,29 @@
29
45
  --btn-bg-color: var(--dt-color-interactive-brand);
30
46
  --btn-text-color: var(--dt-color-content-interactive-primary);
31
47
 
32
- min-block-size: var(--btn-min-block-size);
48
+ // Spinner sizes defaults - currently set for the medium button styles
49
+ --spinner-size-s: 20px;
50
+ --spinner-size-m: 24px;
51
+ --spinner-border-width-s: 2.5px;
52
+ --spinner-border-width-m: 3px;
53
+ --spinner-size: var(--spinner-size-m);
54
+ --spinner-border-width: var(--spinner-border-width-m);
55
+
56
+ // Spinner colors - currently set for the primary button styles
57
+ --spinner-base-color-h: var(--dt-color-content-interactive-primary-h);
58
+ --spinner-base-color-s: var(--dt-color-content-interactive-primary-s);
59
+ --spinner-base-color-l: var(--dt-color-content-interactive-primary-l);
60
+ --spinner-left-color-opacity: 0.35;
61
+ --spinner-left-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), var(--spinner-left-color-opacity));
62
+ --spinner-right-color: hsl(var(--spinner-base-color-h), var(--spinner-base-color-s), var(--spinner-base-color-l), 1);
63
+
64
+ // Spinner animations
65
+ --spinner-animation-duration: 1.15s;
66
+ --spinner-animation-timing-function: linear;
67
+ --spinner-animation-iteration-count: infinite;
68
+
69
+ position: relative;
70
+ box-sizing: border-box;
33
71
  padding: var(--btn-padding);
34
72
  border: none;
35
73
  border-radius: var(--btn-border-radius);
@@ -102,6 +140,9 @@
102
140
  &[variant='secondary'] {
103
141
  --btn-bg-color: var(--dt-color-interactive-secondary);
104
142
  --btn-text-color: var(--dt-color-content-interactive-secondary);
143
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
144
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
145
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
105
146
 
106
147
  @include button-interactive-states('--dt-color-interactive-secondary');
107
148
  }
@@ -109,6 +150,9 @@
109
150
  &[variant='outline'] {
110
151
  --btn-bg-color: var(--dt-color-container-default);
111
152
  --btn-text-color: var(--dt-color-content-interactive-secondary);
153
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
154
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
155
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
112
156
 
113
157
  border: 1px solid var(--dt-color-border-strong);
114
158
 
@@ -118,6 +162,9 @@
118
162
  &[variant='ghost'] {
119
163
  --btn-bg-color: transparent;
120
164
  --btn-text-color: var(--dt-color-content-link);
165
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
166
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
167
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
121
168
 
122
169
  @include button-interactive-states('--dt-color-container-default');
123
170
  }
@@ -125,6 +172,9 @@
125
172
  &[variant='inverse'] {
126
173
  --btn-bg-color: var(--dt-color-interactive-inverse);
127
174
  --btn-text-color: var(--dt-color-content-interactive-secondary);
175
+ --spinner-base-color-h: var(--dt-color-content-interactive-secondary-h);
176
+ --spinner-base-color-s: var(--dt-color-content-interactive-secondary-s);
177
+ --spinner-base-color-l: var(--dt-color-content-interactive-secondary-l);
128
178
 
129
179
  @include button-interactive-states('--dt-color-interactive-inverse');
130
180
  }
@@ -132,6 +182,9 @@
132
182
  &[variant='ghost-inverse'] {
133
183
  --btn-bg-color: transparent;
134
184
  --btn-text-color: var(--dt-color-content-interactive-primary);
185
+ --spinner-base-color-h: var(--dt-color-content-interactive-primary-h);
186
+ --spinner-base-color-s: var(--dt-color-content-interactive-primary-s);
187
+ --spinner-base-color-l: var(--dt-color-content-interactive-primary-l);
135
188
 
136
189
  @include button-interactive-states('--dt-color-container-inverse');
137
190
  }
@@ -161,18 +214,24 @@
161
214
  --btn-padding: 6px var(--dt-spacing-b);
162
215
  --btn-font-size: calc(var(--dt-font-size-14) * 1px);
163
216
  --btn-line-height: calc(var(--dt-font-size-14-line-height) * 1px);
217
+ --spinner-size: var(--spinner-size-s);
218
+ --spinner-border-width: var(--spinner-border-width-s);
164
219
  }
165
220
 
166
221
  &[size='small-expressive'] {
167
222
  --btn-padding: 6px var(--dt-spacing-d);
168
223
  --btn-font-size: calc(var(--dt-font-size-20) * 1px);
169
224
  --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);
225
+ --spinner-size: var(--spinner-size-s);
226
+ --spinner-border-width: var(--spinner-border-width-s);
170
227
  }
171
228
 
172
229
  &[size='small-productive'] {
173
230
  --btn-padding: 8px var(--dt-spacing-d);
174
231
  --btn-font-size: calc(var(--dt-font-size-16) * 1px);
175
232
  --btn-line-height: calc(var(--dt-font-size-16-line-height) * 1px);
233
+ --spinner-size: var(--spinner-size-s);
234
+ --spinner-border-width: var(--spinner-border-width-s);
176
235
  }
177
236
 
178
237
  &[size='medium'] {
@@ -183,5 +242,39 @@
183
242
  --btn-padding: 14px var(--dt-spacing-e);
184
243
  --btn-font-size: calc(var(--dt-font-size-20) * 1px);
185
244
  --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px);
245
+ --spinner-size: var(--spinner-size-m);
246
+ --spinner-border-width: var(--spinner-border-width-m);
247
+ }
248
+
249
+ &:before {
250
+ content: '';
251
+
252
+ // Centre the spinner over the top of the button text
253
+ position: absolute;
254
+ left: 50%;
255
+ top: 50%;
256
+ translate: -50% -50%;
257
+
258
+ height: var(--spinner-size);
259
+ width: var(--spinner-size);
260
+ display: block;
261
+ background-color: transparent;
262
+ border-radius: 50%;
263
+ border-color: var(--spinner-left-color) var(--spinner-right-color) var(--spinner-right-color) var(--spinner-left-color);
264
+ border-width: var(--spinner-border-width);
265
+ border-style: solid;
266
+ will-change: transform;
267
+ opacity: 0;
268
+ }
269
+
270
+ &[isLoading] {
271
+ &:before {
272
+ animation: rotate360 var(--spinner-animation-duration) var(--spinner-animation-timing-function) var(--spinner-animation-iteration-count);
273
+ opacity: 1;
274
+ }
275
+
276
+ & .o-btn-text {
277
+ opacity: 0;
278
+ }
186
279
  }
187
280
  }
package/src/defs.ts CHANGED
@@ -4,28 +4,27 @@ export const variants = ['primary', 'secondary', 'outline', 'ghost', 'inverse',
4
4
 
5
5
  export interface ButtonProps {
6
6
  /**
7
- * (Optional) What size the button should be.
8
- * @default "medium"
7
+ * What size the button should be.
9
8
  */
10
9
  size: typeof sizes[number];
11
10
  /**
12
- * (Optional) What type attribute should be applied to the button. For example submit, button or menu.
13
- * @default "submit"
11
+ * What type attribute should be applied to the button. For example submit, button or menu.
14
12
  */
15
13
  type: typeof types[number];
16
14
  /**
17
- * (Optional) What style variant the button should be such as primary, outline or ghost.
18
- * @default "primary"
15
+ * What style variant the button should be such as primary, outline or ghost.
19
16
  */
20
17
  variant: typeof variants[number];
21
18
  /**
22
- * (Optional) When true, the button element is disabled.
23
- * @default false
19
+ * When true, the button element is disabled.
24
20
  */
25
21
  disabled: boolean;
26
22
  /**
27
- * (Optional) When true, the button element will occupy the full width of its container.
28
- * @default false
23
+ * When true, the button element will occupy the full width of its container.
29
24
  */
30
25
  isFullWidth: boolean;
26
+ /**
27
+ * When true, displays a loading indicator inside the button.
28
+ */
29
+ isLoading: boolean;
31
30
  }
package/src/index.ts CHANGED
@@ -16,7 +16,7 @@ export {
16
16
 
17
17
  const componentSelector = 'pie-button';
18
18
 
19
- export class PieButton extends LitElement {
19
+ export class PieButton extends LitElement implements ButtonProps {
20
20
  @property()
21
21
  @validPropertyValues(componentSelector, sizes, 'medium')
22
22
  public size: ButtonProps['size'] = 'medium';
@@ -32,12 +32,15 @@ export class PieButton extends LitElement {
32
32
  @property({ type: Boolean })
33
33
  public disabled = false;
34
34
 
35
+ @property({ type: Boolean, reflect: true })
36
+ public isLoading = false;
37
+
35
38
  @property({ type: Boolean })
36
39
  public isFullWidth = false;
37
40
 
38
41
  render () {
39
42
  const {
40
- type, disabled, isFullWidth, variant, size,
43
+ type, disabled, isFullWidth, variant, size, isLoading,
41
44
  } = this;
42
45
 
43
46
  return html`
@@ -47,11 +50,16 @@ export class PieButton extends LitElement {
47
50
  variant=${variant}
48
51
  size=${size}
49
52
  ?disabled=${disabled}
50
- ?isFullWidth=${isFullWidth}>
51
- <slot></slot>
53
+ ?isFullWidth=${isFullWidth}
54
+ ?isLoading=${isLoading}>
55
+ <span class="o-btn-text"><slot></slot></span>
52
56
  </button>`;
53
57
  }
54
58
 
59
+ focus () {
60
+ this.shadowRoot?.querySelector('button')?.focus();
61
+ }
62
+
55
63
  // Renders a `CSSResult` generated from SCSS by Vite
56
64
  static styles = unsafeCSS(styles);
57
65
  }
@@ -21,10 +21,11 @@ const props: PropObject = {
21
21
  type: 'button', // Changing the type does not affect the appearance of the button
22
22
  isFullWidth: [true, false],
23
23
  disabled: [true, false],
24
+ isLoading: [true, false],
24
25
  };
25
26
 
26
27
  // Renders a <pie-button> HTML string with the given prop values
27
- const renderTestPieButton = (propVals: WebComponentPropValues) => `<pie-button variant="${propVals.variant}" size="${propVals.size}" type="${propVals.type}" ${propVals.isFullWidth ? 'isFullWidth' : ''} ${propVals.disabled ? 'disabled' : ''}>Hello world</pie-button>`;
28
+ const renderTestPieButton = (propVals: WebComponentPropValues) => `<pie-button variant="${propVals.variant}" size="${propVals.size}" type="${propVals.type}" ${propVals.isFullWidth ? 'isFullWidth' : ''} ${propVals.disabled ? 'disabled' : ''} ${propVals.isLoading ? 'isLoading' : ''}>Hello world</pie-button>`;
28
29
 
29
30
  const componentPropsMatrix : WebComponentPropValues[] = getAllPropCombinations(props);
30
31
  const componentPropsMatrixByVariant: Record<string, WebComponentPropValues[]> = splitCombinationsByPropertyValue(componentPropsMatrix, 'variant');
@@ -48,7 +49,7 @@ test.beforeEach(async ({ page, mount }) => {
48
49
  componentVariants.forEach((variant) => test(`Render all prop variations for Variant: ${variant}`, async ({ page, mount }) => {
49
50
  await Promise.all(componentPropsMatrixByVariant[variant].map(async (combo: WebComponentPropValues) => {
50
51
  const testComponent: WebComponentTestInput = createTestWebComponent(combo, renderTestPieButton);
51
- const propKeyValues = `size: ${testComponent.propValues.size}, isFullWidth: ${testComponent.propValues.isFullWidth}, disabled: ${testComponent.propValues.disabled}`;
52
+ const propKeyValues = `size: ${testComponent.propValues.size}, isFullWidth: ${testComponent.propValues.isFullWidth}, disabled: ${testComponent.propValues.disabled}, isLoading: ${testComponent.propValues.isLoading}`;
52
53
  const darkMode = variant === 'inverse' || variant === 'ghost-inverse';
53
54
 
54
55
  await mount(