@fluid-topics/ft-ripple 0.1.17 → 0.1.18

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.
@@ -5,10 +5,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { css, html, } from "lit";
8
- import { property, query } from "lit/decorators.js";
9
- import { Ripple } from "@material/mwc-ripple";
10
- import { RippleHandlers } from "@material/mwc-ripple/ripple-handlers";
11
- import { customElement, designSystemVariables, FtCssVariable, FtLitElement } from "@fluid-topics/ft-wc-utils";
8
+ import { property, query, state } from "lit/decorators.js";
9
+ import { classMap } from "lit/directives/class-map.js";
10
+ import { designSystemVariables, FtCssVariable, FtLitElement } from "@fluid-topics/ft-wc-utils";
12
11
  export const FtRippleCssVariables = {
13
12
  color: FtCssVariable.extend("--ft-ripple-color", designSystemVariables.colorContent),
14
13
  primaryColor: FtCssVariable.extend("--ft-ripple-primary-color", FtCssVariable.extend("--ft-ripple-color", designSystemVariables.colorPrimary)),
@@ -17,9 +16,8 @@ export const FtRippleCssVariables = {
17
16
  opacityContentOnSurfaceHover: FtCssVariable.external(designSystemVariables.opacityContentOnSurfaceHover, "Design system"),
18
17
  opacityContentOnSurfaceFocused: FtCssVariable.external(designSystemVariables.opacityContentOnSurfaceFocused, "Design system"),
19
18
  opacityContentOnSurfaceSelected: FtCssVariable.external(designSystemVariables.opacityContentOnSurfaceSelected, "Design system"),
20
- opacityContentOnSurfaceDragged: FtCssVariable.external(designSystemVariables.opacityContentOnSurfaceDragged, "Design system"),
21
19
  };
22
- let FtRipple = class FtRipple extends FtLitElement {
20
+ export class FtRipple extends FtLitElement {
23
21
  constructor() {
24
22
  super(...arguments);
25
23
  this.primary = false;
@@ -28,100 +26,276 @@ let FtRipple = class FtRipple extends FtLitElement {
28
26
  this.activated = false;
29
27
  this.selected = false;
30
28
  this.disabled = false;
31
- }
32
- //language=css
33
- getStyles() {
34
- return css `
35
- :host {
36
- display: contents;
37
-
38
- --mdc-ripple-color: ${FtRippleCssVariables.color};
39
- --mdc-ripple-press-opacity: ${FtRippleCssVariables.opacityContentOnSurfacePressed};
40
- --mdc-ripple-hover-opacity: ${FtRippleCssVariables.opacityContentOnSurfaceHover};
41
- --mdc-ripple-focus-opacity: ${FtRippleCssVariables.opacityContentOnSurfaceFocused};
42
- --mdc-ripple-selected-opacity: ${FtRippleCssVariables.opacityContentOnSurfaceSelected};
43
- --mdc-ripple-activated-opacity: ${FtRippleCssVariables.opacityContentOnSurfaceDragged};
29
+ this.hovered = false;
30
+ this.focused = false;
31
+ this.pressed = false;
32
+ this.rippling = false;
33
+ this.rippleSize = 0;
34
+ this.originX = 0;
35
+ this.originY = 0;
36
+ this.resizeObserver = new ResizeObserver(() => this.setRippleSize());
37
+ this.onTransitionStart = (e) => {
38
+ if (e.propertyName === "transform") {
39
+ this.rippling = this.pressed;
44
40
  }
45
-
46
- mwc-ripple.ft-ripple--secondary {
47
- --mdc-ripple-color: ${FtRippleCssVariables.secondaryColor};
48
- }
49
-
50
- mwc-ripple.ft-ripple--primary {
51
- --mdc-ripple-color: ${FtRippleCssVariables.primaryColor};
41
+ };
42
+ this.onTransitionEnd = (e) => {
43
+ if (e.propertyName === "transform") {
44
+ this.rippling = false;
52
45
  }
53
- `;
46
+ };
47
+ this.moveRipple = (e) => {
48
+ var _a, _b;
49
+ let { x, y } = this.getCoordinates(e);
50
+ let rect = (_b = (_a = this.ripple) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) !== null && _b !== void 0 ? _b : { x: 0, y: 0, width: 0, height: 0 };
51
+ this.originX = Math.round(x != null ? x - rect.x : rect.width / 2);
52
+ this.originY = Math.round(y != null ? y - rect.y : rect.height / 2);
53
+ };
54
+ this.startPress = (e) => {
55
+ this.moveRipple(e);
56
+ this.pressed = !this.isIgnored(e);
57
+ };
58
+ this.endPress = () => {
59
+ this.pressed = false;
60
+ };
61
+ this.startHover = (e) => {
62
+ this.hovered = !this.isIgnored(e);
63
+ };
64
+ this.endHover = () => {
65
+ this.hovered = false;
66
+ };
67
+ this.startFocus = (e) => {
68
+ this.focused = !this.isIgnored(e);
69
+ };
70
+ this.endFocus = () => {
71
+ this.focused = false;
72
+ };
54
73
  }
55
- getTemplate() {
74
+ render() {
75
+ let classes = {
76
+ "ft-ripple": true,
77
+ "ft-ripple--primary": this.primary,
78
+ "ft-ripple--secondary": this.secondary,
79
+ "ft-ripple--unbounded": this.unbounded,
80
+ "ft-ripple--selected": (this.selected || this.activated) && !this.disabled,
81
+ "ft-ripple--pressed": (this.pressed || this.rippling) && !this.disabled,
82
+ "ft-ripple--hovered": this.hovered && !this.disabled,
83
+ "ft-ripple--focused": this.focused && !this.disabled,
84
+ };
56
85
  return html `
57
- <mwc-ripple
58
- class="${this.primary ? "ft-ripple--primary" : this.secondary ? "ft-ripple--secondary" : ""}"
59
- ?unbounded=${this.unbounded}
60
- ?activated=${this.activated}
61
- ?selected=${this.selected}
62
- ?disabled=${this.disabled}
63
- ></mwc-ripple>
86
+ <style>
87
+ .ft-ripple .ft-ripple--effect,
88
+ .ft-ripple.ft-ripple--unbounded .ft-ripple--background {
89
+ width: ${this.rippleSize}px;
90
+ height: ${this.rippleSize}px;
91
+ }
92
+
93
+ .ft-ripple .ft-ripple--effect {
94
+ left: ${this.originX}px;
95
+ top: ${this.originY}px;
96
+ }
97
+ </style>
98
+ <div class="${classMap(classes)}">
99
+ <div class="ft-ripple--background"></div>
100
+ <div class="ft-ripple--effect"></div>
101
+ </div>
64
102
  `;
65
103
  }
104
+ contentAvailableCallback(props) {
105
+ super.contentAvailableCallback(props);
106
+ if (this.ripple) {
107
+ this.resizeObserver.observe(this.ripple);
108
+ }
109
+ if (this.rippleEffect && this.rippleEffect.ontransitionstart !== this.onTransitionStart) {
110
+ this.rippleEffect.ontransitionstart = this.onTransitionStart;
111
+ this.rippleEffect.ontransitionend = this.onTransitionEnd;
112
+ }
113
+ }
66
114
  updated(props) {
67
115
  super.updated(props);
68
116
  if (props.has("disabled") && this.disabled) {
69
117
  this.endRipple();
70
118
  }
119
+ if (props.has("unbounded")) {
120
+ this.setRippleSize();
121
+ }
71
122
  }
72
123
  endRipple() {
73
- var _a, _b, _c;
74
- (_a = this.rippleHandlers) === null || _a === void 0 ? void 0 : _a.endHover();
75
- (_b = this.rippleHandlers) === null || _b === void 0 ? void 0 : _b.endFocus();
76
- (_c = this.rippleHandlers) === null || _c === void 0 ? void 0 : _c.endPress();
124
+ this.endHover();
125
+ this.endFocus();
126
+ this.endPress();
127
+ this.rippling = false;
128
+ }
129
+ setRippleSize() {
130
+ if (this.ripple) {
131
+ const rect = this.ripple.getBoundingClientRect();
132
+ this.rippleSize = (this.unbounded ? 1 : 1.7) * Math.max(rect.width, rect.height);
133
+ }
77
134
  }
78
135
  connectedCallback() {
79
136
  var _a;
80
137
  super.connectedCallback();
81
- const parent = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.host.parentNode;
138
+ const parent = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.host.parentElement;
82
139
  if (parent) {
83
- const rh = new RippleHandlers(async () => this.mwcRipple);
84
- const startPress = (...endEvents) => {
85
- return (startEvent) => {
86
- endEvents.forEach(endEvent => window.addEventListener(endEvent, rh.endPress, { once: true }));
87
- rh.startPress(startEvent);
88
- };
140
+ this.setupFor(parent);
141
+ }
142
+ this.setRippleSize();
143
+ }
144
+ setupFor(target) {
145
+ this.onDisconnect && this.onDisconnect();
146
+ this.target = target;
147
+ target.setAttribute("data-is-ft-ripple-target", "true");
148
+ const startPress = (...endEvents) => {
149
+ return (startEvent) => {
150
+ endEvents.forEach(endEvent => window.addEventListener(endEvent, this.endPress, { once: true }));
151
+ this.startPress(startEvent);
89
152
  };
90
- const mouseDownHandler = startPress("mouseup");
91
- const touchStartHandler = startPress("touchend", "touchcancel");
92
- const keyDownHandler = (e) => {
93
- if (["Enter", " "].includes(e.key)) {
94
- startPress("keyup")();
153
+ };
154
+ const mouseDownHandler = startPress("mouseup", "contextmenu");
155
+ const touchStartHandler = startPress("touchend", "touchcancel");
156
+ const keyDownHandler = (e) => {
157
+ if (["Enter", " "].includes(e.key)) {
158
+ startPress("keyup")(e);
159
+ }
160
+ };
161
+ target.addEventListener("mouseover", this.startHover);
162
+ target.addEventListener("mousemove", this.moveRipple);
163
+ target.addEventListener("mouseleave", this.endHover);
164
+ target.addEventListener("mousedown", mouseDownHandler);
165
+ target.addEventListener("touchstart", touchStartHandler);
166
+ target.addEventListener("touchmove", this.moveRipple);
167
+ target.addEventListener("keydown", keyDownHandler);
168
+ target.addEventListener("focus", this.startFocus);
169
+ target.addEventListener("blur", this.endFocus);
170
+ this.onDisconnect = () => {
171
+ target.removeAttribute("data-is-ft-ripple-target");
172
+ target.removeEventListener("mouseover", this.startHover);
173
+ target.removeEventListener("mousemove", this.moveRipple);
174
+ target.removeEventListener("mouseleave", this.endHover);
175
+ target.removeEventListener("mousedown", mouseDownHandler);
176
+ target.removeEventListener("touchstart", touchStartHandler);
177
+ target.removeEventListener("touchmove", this.moveRipple);
178
+ target.removeEventListener("keydown", keyDownHandler);
179
+ target.removeEventListener("focus", this.startFocus);
180
+ target.removeEventListener("blur", this.endFocus);
181
+ this.onDisconnect = undefined;
182
+ };
183
+ }
184
+ getCoordinates(e) {
185
+ const mouseEvent = e;
186
+ const touchEvent = e;
187
+ let x, y;
188
+ if (mouseEvent.x != null) {
189
+ ({ x, y } = mouseEvent);
190
+ }
191
+ else if (touchEvent.touches != null) {
192
+ x = touchEvent.touches[0].clientX;
193
+ y = touchEvent.touches[0].clientY;
194
+ }
195
+ return { x, y };
196
+ }
197
+ isIgnored(e) {
198
+ if (this.disabled) {
199
+ return true;
200
+ }
201
+ if (e != null) {
202
+ for (let t of e.composedPath()) {
203
+ if (t === this.target) {
204
+ break;
95
205
  }
96
- };
97
- parent.addEventListener("mouseenter", rh.startHover);
98
- parent.addEventListener("mouseleave", rh.endHover);
99
- parent.addEventListener("mousedown", mouseDownHandler);
100
- parent.addEventListener("touchstart", touchStartHandler);
101
- parent.addEventListener("keydown", keyDownHandler);
102
- parent.addEventListener("focus", rh.startFocus);
103
- parent.addEventListener("blur", rh.endFocus);
104
- this.onDisconnect = () => {
105
- parent.removeEventListener("mouseenter", rh.startHover);
106
- parent.removeEventListener("mouseleave", rh.endHover);
107
- parent.removeEventListener("mousedown", mouseDownHandler);
108
- parent.removeEventListener("touchstart", touchStartHandler);
109
- parent.removeEventListener("keydown", keyDownHandler);
110
- parent.removeEventListener("focus", rh.startFocus);
111
- parent.removeEventListener("blur", rh.endFocus);
112
- };
113
- this.rippleHandlers = rh;
206
+ const anotherRippleExists = "hasAttribute" in t && t.hasAttribute("data-is-ft-ripple-target");
207
+ if (anotherRippleExists) {
208
+ return true;
209
+ }
210
+ }
114
211
  }
212
+ return false;
115
213
  }
116
214
  disconnectedCallback() {
117
215
  super.disconnectedCallback();
118
216
  this.onDisconnect && this.onDisconnect();
217
+ this.resizeObserver.disconnect();
119
218
  this.endRipple();
120
219
  }
121
- };
122
- FtRipple.elementDefinitions = {
123
- "mwc-ripple": Ripple,
124
- };
220
+ }
221
+ FtRipple.elementDefinitions = {};
222
+ //language=css
223
+ FtRipple.styles = css `
224
+ :host {
225
+ display: contents;
226
+ }
227
+
228
+ .ft-ripple {
229
+ position: absolute;
230
+ inset: 0;
231
+ pointer-events: none;
232
+ }
233
+
234
+ .ft-ripple:not(.ft-ripple--unbounded) {
235
+ overflow: hidden;
236
+ }
237
+
238
+ .ft-ripple .ft-ripple--background,
239
+ .ft-ripple .ft-ripple--effect {
240
+ position: absolute;
241
+ opacity: 0;
242
+ background-color: ${FtRippleCssVariables.color};
243
+ }
244
+
245
+ .ft-ripple.ft-ripple--secondary .ft-ripple--background,
246
+ .ft-ripple.ft-ripple--secondary .ft-ripple--effect {
247
+ background-color: ${FtRippleCssVariables.secondaryColor};
248
+ }
249
+
250
+ .ft-ripple.ft-ripple--primary .ft-ripple--background,
251
+ .ft-ripple.ft-ripple--primary .ft-ripple--effect {
252
+ background-color: ${FtRippleCssVariables.primaryColor};
253
+ }
254
+
255
+ .ft-ripple .ft-ripple--background {
256
+ top: 0;
257
+ left: 0;
258
+ height: 100%;
259
+ width: 100%;
260
+ }
261
+
262
+ .ft-ripple .ft-ripple--effect,
263
+ .ft-ripple.ft-ripple--unbounded .ft-ripple--background {
264
+ border-radius: 50%;
265
+ }
266
+
267
+ .ft-ripple .ft-ripple--effect {
268
+ transform: translate(-50%, -50%) scale(0.15);
269
+ transition: transform 300ms ease, opacity 75ms linear;
270
+ }
271
+
272
+ .ft-ripple.ft-ripple--unbounded .ft-ripple--effect,
273
+ .ft-ripple.ft-ripple--unbounded .ft-ripple--background {
274
+ left: 50%;
275
+ top: 50%;
276
+ }
277
+
278
+ .ft-ripple.ft-ripple--unbounded .ft-ripple--background {
279
+ transform: translate(-50%, -50%);
280
+ }
281
+
282
+ .ft-ripple.ft-ripple--hovered .ft-ripple--background {
283
+ opacity: ${FtRippleCssVariables.opacityContentOnSurfaceHover};
284
+ }
285
+
286
+ .ft-ripple.ft-ripple--selected .ft-ripple--background {
287
+ opacity: ${FtRippleCssVariables.opacityContentOnSurfaceSelected};
288
+ }
289
+
290
+ .ft-ripple.ft-ripple--focused .ft-ripple--background {
291
+ opacity: ${FtRippleCssVariables.opacityContentOnSurfaceFocused};
292
+ }
293
+
294
+ .ft-ripple.ft-ripple--pressed .ft-ripple--effect {
295
+ opacity: ${FtRippleCssVariables.opacityContentOnSurfacePressed};
296
+ transform: translate(-50%, -50%) scale(1);
297
+ }
298
+ `;
125
299
  __decorate([
126
300
  property({ type: Boolean })
127
301
  ], FtRipple.prototype, "primary", void 0);
@@ -141,10 +315,30 @@ __decorate([
141
315
  property({ type: Boolean })
142
316
  ], FtRipple.prototype, "disabled", void 0);
143
317
  __decorate([
144
- query("mwc-ripple")
145
- ], FtRipple.prototype, "mwcRipple", void 0);
146
- FtRipple = __decorate([
147
- customElement("ft-ripple")
148
- ], FtRipple);
149
- export { FtRipple };
318
+ state()
319
+ ], FtRipple.prototype, "hovered", void 0);
320
+ __decorate([
321
+ state()
322
+ ], FtRipple.prototype, "focused", void 0);
323
+ __decorate([
324
+ state()
325
+ ], FtRipple.prototype, "pressed", void 0);
326
+ __decorate([
327
+ state()
328
+ ], FtRipple.prototype, "rippling", void 0);
329
+ __decorate([
330
+ state()
331
+ ], FtRipple.prototype, "rippleSize", void 0);
332
+ __decorate([
333
+ state()
334
+ ], FtRipple.prototype, "originX", void 0);
335
+ __decorate([
336
+ state()
337
+ ], FtRipple.prototype, "originY", void 0);
338
+ __decorate([
339
+ query(".ft-ripple")
340
+ ], FtRipple.prototype, "ripple", void 0);
341
+ __decorate([
342
+ query(".ft-ripple--effect")
343
+ ], FtRipple.prototype, "rippleEffect", void 0);
150
344
  //# sourceMappingURL=ft-ripple.js.map