@limetech/lime-elements 37.71.0 → 37.72.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/3d-tilt-hover-effect-f64da0a8.js +162 -0
  3. package/dist/cjs/3d-tilt-hover-effect-f64da0a8.js.map +1 -0
  4. package/dist/cjs/limel-card.cjs.entry.js +9 -2
  5. package/dist/cjs/limel-card.cjs.entry.js.map +1 -1
  6. package/dist/cjs/limel-info-tile.cjs.entry.js +13 -8
  7. package/dist/cjs/limel-info-tile.cjs.entry.js.map +1 -1
  8. package/dist/collection/components/card/card.css +76 -37
  9. package/dist/collection/components/card/card.js +9 -2
  10. package/dist/collection/components/card/card.js.map +1 -1
  11. package/dist/collection/components/info-tile/info-tile.css +73 -38
  12. package/dist/collection/components/info-tile/info-tile.js +13 -8
  13. package/dist/collection/components/info-tile/info-tile.js.map +1 -1
  14. package/dist/collection/style/mixins.scss +114 -0
  15. package/dist/collection/util/3d-tilt-hover-effect.js +157 -0
  16. package/dist/collection/util/3d-tilt-hover-effect.js.map +1 -0
  17. package/dist/esm/3d-tilt-hover-effect-a76fcd43.js +160 -0
  18. package/dist/esm/3d-tilt-hover-effect-a76fcd43.js.map +1 -0
  19. package/dist/esm/limel-card.entry.js +10 -3
  20. package/dist/esm/limel-card.entry.js.map +1 -1
  21. package/dist/esm/limel-info-tile.entry.js +14 -9
  22. package/dist/esm/limel-info-tile.entry.js.map +1 -1
  23. package/dist/lime-elements/lime-elements.esm.js +1 -1
  24. package/dist/lime-elements/p-05c10bed.entry.js +2 -0
  25. package/dist/lime-elements/p-05c10bed.entry.js.map +1 -0
  26. package/dist/lime-elements/p-23bc6de0.js +2 -0
  27. package/dist/lime-elements/p-23bc6de0.js.map +1 -0
  28. package/dist/lime-elements/p-a0944503.entry.js +2 -0
  29. package/dist/lime-elements/p-a0944503.entry.js.map +1 -0
  30. package/dist/lime-elements/style/mixins.scss +114 -0
  31. package/dist/scss/mixins.scss +114 -0
  32. package/dist/types/components/card/card.d.ts +4 -0
  33. package/dist/types/components/info-tile/info-tile.d.ts +5 -1
  34. package/dist/types/util/3d-tilt-hover-effect.d.ts +118 -0
  35. package/package.json +1 -1
  36. package/dist/lime-elements/p-32844d2b.entry.js +0 -2
  37. package/dist/lime-elements/p-32844d2b.entry.js.map +0 -1
  38. package/dist/lime-elements/p-ca929a0e.entry.js +0 -2
  39. package/dist/lime-elements/p-ca929a0e.entry.js.map +0 -1
@@ -1,6 +1,7 @@
1
- import { h } from '@stencil/core';
1
+ import { h, Host, } from '@stencil/core';
2
2
  import { isItem } from '../action-bar/isItem';
3
3
  import { getIconName } from '../icon/get-icon-props';
4
+ import { getMouseEventHandlers } from '../../util/3d-tilt-hover-effect';
4
5
  /**
5
6
  * Card is a component that displays content about a single topic,
6
7
  * in a structured way. It can contain a header, and some supporting media such
@@ -32,8 +33,13 @@ export class Card {
32
33
  this.clickable = false;
33
34
  this.orientation = 'portrait';
34
35
  }
36
+ componentWillLoad() {
37
+ const { handleMouseEnter, handleMouseLeave } = getMouseEventHandlers(this.host);
38
+ this.handleMouseEnter = handleMouseEnter;
39
+ this.handleMouseLeave = handleMouseLeave;
40
+ }
35
41
  render() {
36
- return (h("section", { tabindex: this.clickable ? 0 : '' }, this.renderImage(), h("div", { class: "body" }, this.renderHeader(), this.renderSlot(), this.renderValue(), this.renderActionBar())));
42
+ return (h(Host, { onMouseEnter: this.handleMouseEnter, onMouseLeave: this.handleMouseLeave }, h("section", { tabindex: this.clickable ? 0 : '' }, this.renderImage(), h("div", { class: "body" }, this.renderHeader(), this.renderSlot(), this.renderValue(), this.renderActionBar()), h("div", { class: "limel-3d-hover-effect-glow" }))));
37
43
  }
38
44
  renderImage() {
39
45
  if (!this.image) {
@@ -278,5 +284,6 @@ export class Card {
278
284
  }
279
285
  }];
280
286
  }
287
+ static get elementRef() { return "host"; }
281
288
  }
282
289
  //# sourceMappingURL=card.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"card.js","sourceRoot":"","sources":["../../../src/components/card/card.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, h, Prop, Event, EventEmitter } from '@stencil/core';\nimport { Image } from '../../global/shared-types/image.types';\nimport { Icon } from '../../global/shared-types/icon.types';\nimport { isItem } from '../action-bar/isItem';\nimport { getIconName } from '../icon/get-icon-props';\nimport { ListSeparator } from '../../global/shared-types/separator.types';\nimport { ActionBarItem } from '../action-bar/action-bar.types';\n\n/**\n * Card is a component that displays content about a single topic,\n * in a structured way. It can contain a header, and some supporting media such\n * as an image or an icon, a body of text, or optional actions.\n *\n * @exampleComponent limel-example-card-basic\n * @exampleComponent limel-example-card-image\n * @exampleComponent limel-example-card-actions\n * @exampleComponent limel-example-card-clickable\n * @exampleComponent limel-example-card-orientation\n * @exampleComponent limel-example-card-slot\n * @exampleComponent limel-example-card-styling\n * @beta\n */\n@Component({\n tag: 'limel-card',\n shadow: true,\n styleUrl: 'card.scss',\n})\nexport class Card {\n /**\n * Heading of the card,\n * to provide a short title about the context.\n */\n @Prop({ reflect: true })\n public heading?: string;\n\n /**\n * Subheading of the card\n * to provide a short description of the context.\n */\n @Prop({ reflect: true })\n public subheading?: string;\n\n /**\n * A hero image to display in the card,\n * to enrich the content with visual information.\n */\n @Prop()\n public image?: Image;\n\n /**\n * An icon, to display along with the heading and subheading.\n */\n @Prop({ reflect: true })\n public icon?: string | Icon;\n\n /**\n * The content of the card.\n * Supports markdown, to provide a rich text experience.\n */\n @Prop()\n public value?: string;\n\n /**\n * Actions to display in the card,\n * to provide the user with options to interact with the content.\n */\n @Prop()\n public actions?: Array<ActionBarItem | ListSeparator> = [];\n\n /**\n * When true, improve the accessibility of the component and hints the user\n * that the card can be interacted width.\n */\n @Prop({ reflect: true })\n public clickable: boolean = false;\n\n /**\n * The orientation of the card,\n * specially useful when the card has an image.\n */\n @Prop({ reflect: true })\n public orientation: 'landscape' | 'portrait' = 'portrait';\n\n /**\n * Fired when a action bar item has been clicked.\n */\n @Event()\n public actionSelected: EventEmitter<ActionBarItem>;\n\n public render() {\n return (\n <section tabindex={this.clickable ? 0 : ''}>\n {this.renderImage()}\n <div class=\"body\">\n {this.renderHeader()}\n {this.renderSlot()}\n {this.renderValue()}\n {this.renderActionBar()}\n </div>\n </section>\n );\n }\n\n private renderImage() {\n if (!this.image) {\n return;\n }\n\n return <img src={this.image.src} alt={this.image.alt} loading=\"lazy\" />;\n }\n\n private renderHeader() {\n if (!this.heading && !this.subheading && !this.icon) {\n return;\n }\n\n return (\n <header>\n {this.renderIcon()}\n <div class=\"headings\">\n {this.renderHeading()}\n {this.renderSubheading()}\n </div>\n </header>\n );\n }\n\n private renderIcon() {\n const icon = getIconName(this.icon);\n const color =\n typeof this.icon !== 'string' ? this.icon?.color : undefined;\n\n if (!icon) {\n return;\n }\n\n return (\n <limel-icon\n style={{\n color: `${color}`,\n }}\n badge={true}\n name={icon}\n />\n );\n }\n\n private renderHeading() {\n if (!this.heading) {\n return;\n }\n\n return <h1>{this.heading}</h1>;\n }\n\n private renderSubheading() {\n if (!this.subheading) {\n return;\n }\n\n return <h2>{this.subheading}</h2>;\n }\n\n private renderSlot() {\n return <slot name=\"component\" />;\n }\n\n private renderValue() {\n return <limel-markdown value={this.value} />;\n }\n\n private handleActionSelect = (\n event: CustomEvent<ActionBarItem | ListSeparator>,\n ) => {\n event.stopPropagation();\n if (isItem(event.detail)) {\n this.actionSelected.emit(event.detail);\n }\n };\n\n private renderActionBar() {\n if (!this.actions.length) {\n return;\n }\n\n return (\n <limel-action-bar\n actions={this.actions}\n onItemSelected={this.handleActionSelect}\n />\n );\n }\n}\n"]}
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../../../src/components/card/card.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n h,\n Prop,\n Event,\n EventEmitter,\n Element,\n Host,\n} from '@stencil/core';\nimport { Image } from '../../global/shared-types/image.types';\nimport { Icon } from '../../global/shared-types/icon.types';\nimport { isItem } from '../action-bar/isItem';\nimport { getIconName } from '../icon/get-icon-props';\nimport { ListSeparator } from '../../global/shared-types/separator.types';\nimport { ActionBarItem } from '../action-bar/action-bar.types';\nimport { getMouseEventHandlers } from '../../util/3d-tilt-hover-effect';\n\n/**\n * Card is a component that displays content about a single topic,\n * in a structured way. It can contain a header, and some supporting media such\n * as an image or an icon, a body of text, or optional actions.\n *\n * @exampleComponent limel-example-card-basic\n * @exampleComponent limel-example-card-image\n * @exampleComponent limel-example-card-actions\n * @exampleComponent limel-example-card-clickable\n * @exampleComponent limel-example-card-orientation\n * @exampleComponent limel-example-card-slot\n * @exampleComponent limel-example-card-styling\n * @beta\n */\n@Component({\n tag: 'limel-card',\n shadow: true,\n styleUrl: 'card.scss',\n})\nexport class Card {\n /**\n * Heading of the card,\n * to provide a short title about the context.\n */\n @Prop({ reflect: true })\n public heading?: string;\n\n /**\n * Subheading of the card\n * to provide a short description of the context.\n */\n @Prop({ reflect: true })\n public subheading?: string;\n\n /**\n * A hero image to display in the card,\n * to enrich the content with visual information.\n */\n @Prop()\n public image?: Image;\n\n /**\n * An icon, to display along with the heading and subheading.\n */\n @Prop({ reflect: true })\n public icon?: string | Icon;\n\n /**\n * The content of the card.\n * Supports markdown, to provide a rich text experience.\n */\n @Prop()\n public value?: string;\n\n /**\n * Actions to display in the card,\n * to provide the user with options to interact with the content.\n */\n @Prop()\n public actions?: Array<ActionBarItem | ListSeparator> = [];\n\n /**\n * When true, improve the accessibility of the component and hints the user\n * that the card can be interacted width.\n */\n @Prop({ reflect: true })\n public clickable: boolean = false;\n\n /**\n * The orientation of the card,\n * specially useful when the card has an image.\n */\n @Prop({ reflect: true })\n public orientation: 'landscape' | 'portrait' = 'portrait';\n\n /**\n * Fired when a action bar item has been clicked.\n */\n @Event()\n public actionSelected: EventEmitter<ActionBarItem>;\n\n @Element()\n private host: HTMLElement;\n\n private handleMouseEnter: () => void;\n private handleMouseLeave: () => void;\n\n public componentWillLoad() {\n const { handleMouseEnter, handleMouseLeave } = getMouseEventHandlers(\n this.host,\n );\n this.handleMouseEnter = handleMouseEnter;\n this.handleMouseLeave = handleMouseLeave;\n }\n\n public render() {\n return (\n <Host\n onMouseEnter={this.handleMouseEnter}\n onMouseLeave={this.handleMouseLeave}\n >\n <section tabindex={this.clickable ? 0 : ''}>\n {this.renderImage()}\n <div class=\"body\">\n {this.renderHeader()}\n {this.renderSlot()}\n {this.renderValue()}\n {this.renderActionBar()}\n </div>\n <div class=\"limel-3d-hover-effect-glow\" />\n </section>\n </Host>\n );\n }\n\n private renderImage() {\n if (!this.image) {\n return;\n }\n\n return <img src={this.image.src} alt={this.image.alt} loading=\"lazy\" />;\n }\n\n private renderHeader() {\n if (!this.heading && !this.subheading && !this.icon) {\n return;\n }\n\n return (\n <header>\n {this.renderIcon()}\n <div class=\"headings\">\n {this.renderHeading()}\n {this.renderSubheading()}\n </div>\n </header>\n );\n }\n\n private renderIcon() {\n const icon = getIconName(this.icon);\n const color =\n typeof this.icon !== 'string' ? this.icon?.color : undefined;\n\n if (!icon) {\n return;\n }\n\n return (\n <limel-icon\n style={{\n color: `${color}`,\n }}\n badge={true}\n name={icon}\n />\n );\n }\n\n private renderHeading() {\n if (!this.heading) {\n return;\n }\n\n return <h1>{this.heading}</h1>;\n }\n\n private renderSubheading() {\n if (!this.subheading) {\n return;\n }\n\n return <h2>{this.subheading}</h2>;\n }\n\n private renderSlot() {\n return <slot name=\"component\" />;\n }\n\n private renderValue() {\n return <limel-markdown value={this.value} />;\n }\n\n private handleActionSelect = (\n event: CustomEvent<ActionBarItem | ListSeparator>,\n ) => {\n event.stopPropagation();\n if (isItem(event.detail)) {\n this.actionSelected.emit(event.detail);\n }\n };\n\n private renderActionBar() {\n if (!this.actions.length) {\n return;\n }\n\n return (\n <limel-action-bar\n actions={this.actions}\n onItemSelected={this.handleActionSelect}\n />\n );\n }\n}\n"]}
@@ -103,7 +103,6 @@
103
103
  --icon-min-size: 2rem;
104
104
  --icon-preferred-size: 60cqh;
105
105
  --icon-max-size: calc(100cqw - 0.5rem);
106
- isolation: isolate;
107
106
  container-type: size;
108
107
  position: relative;
109
108
  display: flex;
@@ -133,43 +132,6 @@ a {
133
132
  border-radius: var(--info-tile-border-radius, 1rem);
134
133
  background-color: var(--info-tile-background-color, var(--lime-elevated-surface-background-color));
135
134
  }
136
- a.is-clickable {
137
- transition: color var(--limel-clickable-transition-speed, 0.4s) ease, background-color var(--limel-clickable-transition-speed, 0.4s) ease, box-shadow var(--limel-clickable-transform-speed, 0.4s) ease, transform var(--limel-clickable-transform-speed, 0.4s) var(--limel-clickable-transform-timing-function, ease);
138
- cursor: pointer;
139
- color: var(--mdc-theme-on-surface);
140
- background-color: var(--info-tile-background-color, var(--lime-elevated-surface-background-color));
141
- box-shadow: var(--button-shadow-normal);
142
- }
143
- a.is-clickable:hover, a.is-clickable:focus, a.is-clickable:focus-visible {
144
- will-change: color, background-color, box-shadow, transform;
145
- }
146
- a.is-clickable:hover {
147
- transform: translate3d(0, -0.04rem, 0);
148
- color: var(--mdc-theme-on-surface);
149
- background-color: var(--info-tile-background-color, var(--lime-elevated-surface-background-color));
150
- box-shadow: var(--button-shadow-hovered);
151
- }
152
- a.is-clickable:active {
153
- --limel-clickable-transform-timing-function: cubic-bezier(
154
- 0.83,
155
- -0.15,
156
- 0.49,
157
- 1.16
158
- );
159
- transform: translate3d(0, 0.05rem, 0);
160
- box-shadow: var(--button-shadow-pressed);
161
- }
162
- a.is-clickable:hover, a.is-clickable:active {
163
- --limel-clickable-transition-speed: 0.2s;
164
- --limel-clickable-transform-speed: 0.16s;
165
- }
166
- a.is-clickable:focus {
167
- outline: none;
168
- }
169
- a.is-clickable:focus-visible {
170
- outline: none;
171
- box-shadow: var(--shadow-depth-8-focused);
172
- }
173
135
 
174
136
  .icon {
175
137
  z-index: 1;
@@ -375,4 +337,77 @@ limel-linear-progress {
375
337
  right: 0.5rem;
376
338
  --icon-max-size: 3rem;
377
339
  }
340
+ }
341
+ .limel-3d-hover-effect-glow {
342
+ transition: background 0.4s ease, opacity 0.4s ease;
343
+ pointer-events: none;
344
+ position: absolute;
345
+ inset: 0;
346
+ border-radius: var(--info-tile-border-radius, 1rem);
347
+ opacity: 0.1;
348
+ background-image: radial-gradient(circle at var(--limel-3d-hover-effect-glow-position, 50% -20%), rgb(var(--color-white), 0.3), rgb(var(--color-white), 0));
349
+ mix-blend-mode: plus-lighter;
350
+ }
351
+ a:hover .limel-3d-hover-effect-glow {
352
+ opacity: 0.5;
353
+ }
354
+ @media (prefers-reduced-motion) {
355
+ a:hover .limel-3d-hover-effect-glow {
356
+ opacity: 0.2;
357
+ }
358
+ }
359
+
360
+ :host(limel-info-tile) {
361
+ isolation: isolate;
362
+ transform-style: preserve-3d;
363
+ perspective: 1000px;
364
+ }
365
+ @media (prefers-reduced-motion) {
366
+ :host(limel-info-tile) {
367
+ perspective: 2000px;
368
+ }
369
+ }
370
+
371
+ a {
372
+ position: relative;
373
+ transition-duration: 0.8s;
374
+ transition-property: transform, box-shadow, background-color;
375
+ transition-timing-function: ease-out;
376
+ transform: scale3d(1, 1, 1) rotate3d(0, 0, 0, 0deg);
377
+ }
378
+ a:focus {
379
+ outline: none;
380
+ }
381
+ a:hover, a:focus, a:focus-visible, a:focus-within {
382
+ will-change: background-color, box-shadow, transform;
383
+ }
384
+ a:hover, a:focus, a:focus-visible, a:active {
385
+ transition-duration: 0.2s;
386
+ }
387
+ a:hover, a:focus-visible {
388
+ box-shadow: var(--button-shadow-hovered), var(--shadow-depth-16);
389
+ }
390
+ a:hover {
391
+ transform: scale3d(1.01, 1.01, 1.01) rotate3d(var(--limel-3d-hover-effect-rotate3d));
392
+ }
393
+ a:focus-visible {
394
+ outline: none;
395
+ transform: scale3d(1.01, 1.01, 1.01);
396
+ }
397
+ a.is-clickable {
398
+ cursor: pointer;
399
+ box-shadow: var(--button-shadow-normal);
400
+ }
401
+ a.is-clickable:hover, a.is-clickable:focus-visible {
402
+ box-shadow: var(--button-shadow-hovered), var(--shadow-depth-16);
403
+ }
404
+ a.is-clickable:active {
405
+ transform: scale3d(1, 1, 1) rotate3d(0, 0, 0, 0deg);
406
+ box-shadow: var(--button-shadow-pressed);
407
+ }
408
+ a.is-clickable:focus-visible {
409
+ box-shadow: var(--shadow-depth-8-focused), var(--button-shadow-hovered);
410
+ }
411
+ a.is-clickable:focus-visible:active {
412
+ box-shadow: var(--shadow-depth-8-focused), var(--button-shadow-pressed);
378
413
  }
@@ -1,4 +1,5 @@
1
- import { h } from '@stencil/core';
1
+ import { h, Host } from '@stencil/core';
2
+ import { getMouseEventHandlers } from '../../util/3d-tilt-hover-effect';
2
3
  /**
3
4
  * This component can be used on places such as a start page or a dashboard.
4
5
  * It offers features for visualizing aggregated data along with supplementary
@@ -76,6 +77,11 @@ export class InfoTile {
76
77
  this.link = undefined;
77
78
  this.progress = undefined;
78
79
  }
80
+ componentWillLoad() {
81
+ const { handleMouseEnter, handleMouseLeave } = getMouseEventHandlers(this.host);
82
+ this.handleMouseEnter = handleMouseEnter;
83
+ this.handleMouseLeave = handleMouseLeave;
84
+ }
79
85
  render() {
80
86
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
81
87
  const extendedAriaLabel = this.checkProps(this === null || this === void 0 ? void 0 : this.prefix) +
@@ -89,13 +95,11 @@ export class InfoTile {
89
95
  this.checkProps((_c = this === null || this === void 0 ? void 0 : this.progress) === null || _c === void 0 ? void 0 : _c.suffix) +
90
96
  this.checkProps((_d = this === null || this === void 0 ? void 0 : this.link) === null || _d === void 0 ? void 0 : _d.title);
91
97
  const link = !this.disabled ? (_e = this.link) === null || _e === void 0 ? void 0 : _e.href : '#';
92
- return [
93
- h("a", { title: (_f = this.link) === null || _f === void 0 ? void 0 : _f.title, href: link, target: (_g = this.link) === null || _g === void 0 ? void 0 : _g.target, tabindex: "0", "aria-label": extendedAriaLabel, "aria-disabled": this.disabled, "aria-busy": this.loading ? 'true' : 'false', "aria-live": "polite", class: {
94
- 'is-clickable': !!((_h = this.link) === null || _h === void 0 ? void 0 : _h.href) && !this.disabled,
95
- 'has-circular-progress': !!((_j = this.progress) === null || _j === void 0 ? void 0 : _j.value) || ((_k = this.progress) === null || _k === void 0 ? void 0 : _k.value) === 0,
96
- } }, this.renderIcon(), this.renderProgress(), h("div", { class: "value-group" }, this.renderPrefix(), h("div", { class: "value-and-suffix" }, this.renderValue(), this.renderSuffix()), this.renderSpinner()), this.renderLabel()),
97
- this.renderNotification(),
98
- ];
98
+ return (h(Host, { onMouseEnter: this.handleMouseEnter, onMouseLeave: this.handleMouseLeave }, h("a", { title: (_f = this.link) === null || _f === void 0 ? void 0 : _f.title, href: link, target: (_g = this.link) === null || _g === void 0 ? void 0 : _g.target, tabindex: "0", "aria-label": extendedAriaLabel, "aria-disabled": this.disabled, "aria-busy": this.loading ? 'true' : 'false', "aria-live": "polite", class: {
99
+ 'is-clickable': !!((_h = this.link) === null || _h === void 0 ? void 0 : _h.href) && !this.disabled,
100
+ 'has-circular-progress': !!((_j = this.progress) === null || _j === void 0 ? void 0 : _j.value) ||
101
+ ((_k = this.progress) === null || _k === void 0 ? void 0 : _k.value) === 0,
102
+ } }, this.renderIcon(), this.renderProgress(), h("div", { class: "value-group" }, this.renderPrefix(), h("div", { class: "value-and-suffix" }, this.renderValue(), this.renderSuffix()), this.renderSpinner()), this.renderLabel()), this.renderNotification(), h("div", { class: "limel-3d-hover-effect-glow" })));
99
103
  }
100
104
  checkProps(propValue) {
101
105
  return !propValue ? '' : propValue + ' ';
@@ -295,5 +299,6 @@ export class InfoTile {
295
299
  }
296
300
  };
297
301
  }
302
+ static get elementRef() { return "host"; }
298
303
  }
299
304
  //# sourceMappingURL=info-tile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"info-tile.js","sourceRoot":"","sources":["../../../src/components/info-tile/info-tile.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, h } from '@stencil/core';\nimport { InfoTileProgress } from '../info-tile/info-tile.types';\nimport { Link } from '../../global/shared-types/link.types';\n\n/**\n * This component can be used on places such as a start page or a dashboard.\n * It offers features for visualizing aggregated data along with supplementary\n * information.\n *\n * If clicking on the component should navigate the user to\n * a new screen or web page, you need to provide a URL,\n * using the `link` property.\n *\n * @exampleComponent limel-example-info-tile\n * @exampleComponent limel-example-info-tile-badge\n * @exampleComponent limel-example-info-tile-progress\n * @exampleComponent limel-example-info-tile-loading\n * @exampleComponent limel-example-info-tile-styling\n */\n@Component({\n tag: 'limel-info-tile',\n shadow: true,\n styleUrl: 'info-tile.scss',\n})\nexport class InfoTile {\n /**\n * A piece of text or number that is the main piece of information\n * which the component is intended to visualize.\n */\n @Prop({ reflect: true })\n public value: number | string;\n\n /**\n * Name of icon for the info tile.\n */\n @Prop()\n public icon?: string;\n\n /**\n * The text to show below the info tile. Long labels will be truncated.\n */\n @Prop({ reflect: true })\n public label?: string = null;\n\n /**\n * A string of text that is visually placed before the value.\n */\n @Prop({ reflect: true })\n public prefix?: string;\n\n /**\n * A string of text that is visually placed after the value.\n */\n @Prop({ reflect: true })\n public suffix?: string;\n\n /**\n * Set to `true` if info tile is disabled.\n */\n @Prop({ reflect: true })\n public disabled? = false;\n\n /**\n * If supplied, the info tile will display a notification badge.\n */\n @Prop({ reflect: true })\n public badge?: number | string;\n\n /**\n * Set to `true` to put the component in the `loading` state.\n * This does _not_ disable the link. To do so, the\n * `disabled` property should be set to `true` as well.\n */\n @Prop({ reflect: true })\n public loading? = false;\n\n /**\n * If supplied, the info tile will be a clickable link.\n *\n * Supplying a value also adds an elevated effect using a shadow,\n * as well as `cursor: pointer`, which appears on hover.\n * While we strongly recommend supplying a link whenever the\n * component should act as a link, if this is not possible, and\n * you need to provide interaction through a click handler,\n * you can still get the correct styling by supplying a `Link`\n * object with the `href` property set to `'#'`.\n */\n @Prop()\n public link?: Link;\n\n /**\n * Properties of the optional circular progress bar.\n *\n * Defaults:\n * - `maxValue`: 100\n * - `suffix`: %\n * - `displayPercentageColors`: false\n *\n * Colors change with intervals of 10 %.\n */\n @Prop()\n public progress?: InfoTileProgress;\n\n public render() {\n const extendedAriaLabel =\n this.checkProps(this?.prefix) +\n this.value +\n ' ' +\n this.checkProps(this?.suffix) +\n this.checkProps(this?.label) +\n '. ' +\n this.checkProps(this?.progress?.prefix) +\n this.checkProps(this?.progress?.value) +\n this.checkProps(this?.progress?.suffix) +\n this.checkProps(this?.link?.title);\n\n const link = !this.disabled ? this.link?.href : '#';\n\n return [\n <a\n title={this.link?.title}\n href={link}\n target={this.link?.target}\n tabindex=\"0\"\n aria-label={extendedAriaLabel}\n aria-disabled={this.disabled}\n aria-busy={this.loading ? 'true' : 'false'}\n aria-live=\"polite\"\n class={{\n 'is-clickable': !!this.link?.href && !this.disabled,\n 'has-circular-progress':\n !!this.progress?.value || this.progress?.value === 0,\n }}\n >\n {this.renderIcon()}\n {this.renderProgress()}\n <div class=\"value-group\">\n {this.renderPrefix()}\n <div class=\"value-and-suffix\">\n {this.renderValue()}\n {this.renderSuffix()}\n </div>\n {this.renderSpinner()}\n </div>\n {this.renderLabel()}\n </a>,\n this.renderNotification(),\n ];\n }\n\n private checkProps(propValue) {\n return !propValue ? '' : propValue + ' ';\n }\n\n private renderPrefix = () => {\n if (this.prefix) {\n return <span class=\"prefix\">{this.prefix}</span>;\n }\n };\n\n private renderValue = () => {\n const characterCount = (this.value ?? '').toString().length;\n\n if (!this.value && this.loading) {\n return <span class=\"value\">···</span>;\n }\n\n if (this.value) {\n return (\n <span\n class={{\n value: true,\n [`ch-${characterCount}`]: true,\n }}\n >\n {this.value}\n </span>\n );\n }\n };\n\n private renderSuffix = () => {\n if (this.suffix) {\n return <span class=\"suffix\">{this.suffix}</span>;\n }\n };\n\n private renderIcon = () => {\n if (this.icon) {\n return <limel-icon class=\"icon\" name={this.icon} />;\n }\n };\n\n private renderProgress = () => {\n if (this.progress?.value || this.progress?.value === 0) {\n return (\n <limel-circular-progress\n class=\"progress\"\n prefix={this.progress.prefix}\n value={this.progress.value}\n suffix={this.progress.suffix}\n maxValue={this.progress.maxValue}\n displayPercentageColors={\n this.progress.displayPercentageColors\n }\n />\n );\n }\n };\n\n private renderLabel = () => {\n if (this.label) {\n return <span class=\"label\">{this.label}</span>;\n }\n };\n\n private renderNotification = () => {\n if (this.badge) {\n return <limel-badge label={this.badge} />;\n }\n };\n\n private renderSpinner = () => {\n if (this.loading) {\n return <limel-linear-progress indeterminate={true} />;\n }\n };\n}\n"]}
1
+ {"version":3,"file":"info-tile.js","sourceRoot":"","sources":["../../../src/components/info-tile/info-tile.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Component, Prop, h, Element, Host } from '@stencil/core';\nimport { InfoTileProgress } from '../info-tile/info-tile.types';\nimport { Link } from '../../global/shared-types/link.types';\nimport { getMouseEventHandlers } from '../../util/3d-tilt-hover-effect';\n\n/**\n * This component can be used on places such as a start page or a dashboard.\n * It offers features for visualizing aggregated data along with supplementary\n * information.\n *\n * If clicking on the component should navigate the user to\n * a new screen or web page, you need to provide a URL,\n * using the `link` property.\n *\n * @exampleComponent limel-example-info-tile\n * @exampleComponent limel-example-info-tile-badge\n * @exampleComponent limel-example-info-tile-progress\n * @exampleComponent limel-example-info-tile-loading\n * @exampleComponent limel-example-info-tile-styling\n */\n@Component({\n tag: 'limel-info-tile',\n shadow: true,\n styleUrl: 'info-tile.scss',\n})\nexport class InfoTile {\n /**\n * A piece of text or number that is the main piece of information\n * which the component is intended to visualize.\n */\n @Prop({ reflect: true })\n public value: number | string;\n\n /**\n * Name of icon for the info tile.\n */\n @Prop()\n public icon?: string;\n\n /**\n * The text to show below the info tile. Long labels will be truncated.\n */\n @Prop({ reflect: true })\n public label?: string = null;\n\n /**\n * A string of text that is visually placed before the value.\n */\n @Prop({ reflect: true })\n public prefix?: string;\n\n /**\n * A string of text that is visually placed after the value.\n */\n @Prop({ reflect: true })\n public suffix?: string;\n\n /**\n * Set to `true` if info tile is disabled.\n */\n @Prop({ reflect: true })\n public disabled? = false;\n\n /**\n * If supplied, the info tile will display a notification badge.\n */\n @Prop({ reflect: true })\n public badge?: number | string;\n\n /**\n * Set to `true` to put the component in the `loading` state.\n * This does _not_ disable the link. To do so, the\n * `disabled` property should be set to `true` as well.\n */\n @Prop({ reflect: true })\n public loading? = false;\n\n /**\n * If supplied, the info tile will be a clickable link.\n *\n * Supplying a value also adds an elevated effect using a shadow,\n * as well as `cursor: pointer`, which appears on hover.\n * While we strongly recommend supplying a link whenever the\n * component should act as a link, if this is not possible, and\n * you need to provide interaction through a click handler,\n * you can still get the correct styling by supplying a `Link`\n * object with the `href` property set to `'#'`.\n */\n @Prop()\n public link?: Link;\n\n /**\n * Properties of the optional circular progress bar.\n *\n * Defaults:\n * - `maxValue`: 100\n * - `suffix`: %\n * - `displayPercentageColors`: false\n *\n * Colors change with intervals of 10 %.\n */\n @Prop()\n public progress?: InfoTileProgress;\n\n @Element()\n private host: HTMLElement;\n\n private handleMouseEnter: () => void;\n private handleMouseLeave: () => void;\n\n public componentWillLoad() {\n const { handleMouseEnter, handleMouseLeave } = getMouseEventHandlers(\n this.host,\n );\n this.handleMouseEnter = handleMouseEnter;\n this.handleMouseLeave = handleMouseLeave;\n }\n\n public render() {\n const extendedAriaLabel =\n this.checkProps(this?.prefix) +\n this.value +\n ' ' +\n this.checkProps(this?.suffix) +\n this.checkProps(this?.label) +\n '. ' +\n this.checkProps(this?.progress?.prefix) +\n this.checkProps(this?.progress?.value) +\n this.checkProps(this?.progress?.suffix) +\n this.checkProps(this?.link?.title);\n\n const link = !this.disabled ? this.link?.href : '#';\n\n return (\n <Host\n onMouseEnter={this.handleMouseEnter}\n onMouseLeave={this.handleMouseLeave}\n >\n <a\n title={this.link?.title}\n href={link}\n target={this.link?.target}\n tabindex=\"0\"\n aria-label={extendedAriaLabel}\n aria-disabled={this.disabled}\n aria-busy={this.loading ? 'true' : 'false'}\n aria-live=\"polite\"\n class={{\n 'is-clickable': !!this.link?.href && !this.disabled,\n 'has-circular-progress':\n !!this.progress?.value ||\n this.progress?.value === 0,\n }}\n >\n {this.renderIcon()}\n {this.renderProgress()}\n <div class=\"value-group\">\n {this.renderPrefix()}\n <div class=\"value-and-suffix\">\n {this.renderValue()}\n {this.renderSuffix()}\n </div>\n {this.renderSpinner()}\n </div>\n {this.renderLabel()}\n </a>\n {this.renderNotification()}\n <div class=\"limel-3d-hover-effect-glow\" />\n </Host>\n );\n }\n\n private checkProps(propValue) {\n return !propValue ? '' : propValue + ' ';\n }\n\n private renderPrefix = () => {\n if (this.prefix) {\n return <span class=\"prefix\">{this.prefix}</span>;\n }\n };\n\n private renderValue = () => {\n const characterCount = (this.value ?? '').toString().length;\n\n if (!this.value && this.loading) {\n return <span class=\"value\">···</span>;\n }\n\n if (this.value) {\n return (\n <span\n class={{\n value: true,\n [`ch-${characterCount}`]: true,\n }}\n >\n {this.value}\n </span>\n );\n }\n };\n\n private renderSuffix = () => {\n if (this.suffix) {\n return <span class=\"suffix\">{this.suffix}</span>;\n }\n };\n\n private renderIcon = () => {\n if (this.icon) {\n return <limel-icon class=\"icon\" name={this.icon} />;\n }\n };\n\n private renderProgress = () => {\n if (this.progress?.value || this.progress?.value === 0) {\n return (\n <limel-circular-progress\n class=\"progress\"\n prefix={this.progress.prefix}\n value={this.progress.value}\n suffix={this.progress.suffix}\n maxValue={this.progress.maxValue}\n displayPercentageColors={\n this.progress.displayPercentageColors\n }\n />\n );\n }\n };\n\n private renderLabel = () => {\n if (this.label) {\n return <span class=\"label\">{this.label}</span>;\n }\n };\n\n private renderNotification = () => {\n if (this.badge) {\n return <limel-badge label={this.badge} />;\n }\n };\n\n private renderSpinner = () => {\n if (this.loading) {\n return <limel-linear-progress indeterminate={true} />;\n }\n };\n}\n"]}
@@ -456,3 +456,117 @@ $clickable-normal-state-transitions: (
456
456
  clip-path: inset(50%);
457
457
  white-space: nowrap;
458
458
  }
459
+
460
+ // This mixin designed to enhance the visual effects,
461
+ // when the `tiltFollowingTheCursor` utility function from `3d-tilt-hover-effect.ts`
462
+ // is implemented in a component.
463
+ // This adds styles to a `<div class"limel-3d-hover-effect-glow" />`, needed to create
464
+ // a glow effect on a 3D element when the parent element is hovered.
465
+ // when the `tiltFollowingTheCursor` utility function from `3d-tilt-hover-effect.ts`
466
+ // Parts of these styles are controlled by the `titleFollowingTheCursor` function.
467
+ @mixin limel-3d-hover-effect-glow($the3dElement, $border-radius) {
468
+ .limel-3d-hover-effect-glow {
469
+ transition:
470
+ background 0.4s ease,
471
+ opacity 0.4s ease;
472
+ pointer-events: none;
473
+
474
+ position: absolute;
475
+ inset: 0;
476
+ border-radius: $border-radius;
477
+
478
+ opacity: 0.1;
479
+ #{$the3dElement}:hover & {
480
+ opacity: 0.5;
481
+ @media (prefers-reduced-motion) {
482
+ opacity: 0.2;
483
+ }
484
+ }
485
+
486
+ background-image: radial-gradient(
487
+ circle at var(--limel-3d-hover-effect-glow-position, 50% -20%),
488
+ rgb(var(--color-white), 0.3),
489
+ rgb(var(--color-white), 0)
490
+ );
491
+
492
+ mix-blend-mode: plus-lighter;
493
+ }
494
+ }
495
+
496
+ // These mixins below are designed to apply the necessary visual effects,
497
+ // when the `tiltFollowingTheCursor` utility function from `3d-tilt-hover-effect.ts`
498
+ // is implemented in a component.
499
+ @mixin parent-of-the-3d-element {
500
+ isolation: isolate;
501
+ transform-style: preserve-3d;
502
+
503
+ perspective: 1000px;
504
+ @media (prefers-reduced-motion) {
505
+ perspective: 2000px;
506
+ }
507
+ }
508
+
509
+ @mixin the-3d-element {
510
+ position: relative;
511
+
512
+ transition-duration: 0.8s;
513
+ transition-property: transform, box-shadow, background-color;
514
+ transition-timing-function: ease-out;
515
+ transform: scale3d(1, 1, 1) rotate3d(0, 0, 0, 0deg);
516
+
517
+ &:focus {
518
+ outline: none;
519
+ }
520
+
521
+ &:hover,
522
+ &:focus,
523
+ &:focus-visible,
524
+ &:focus-within {
525
+ will-change: background-color, box-shadow, transform;
526
+ }
527
+
528
+ &:hover,
529
+ &:focus,
530
+ &:focus-visible,
531
+ &:active {
532
+ transition-duration: 0.2s;
533
+ }
534
+
535
+ &:hover,
536
+ &:focus-visible {
537
+ box-shadow: var(--button-shadow-hovered), var(--shadow-depth-16);
538
+ }
539
+
540
+ &:hover {
541
+ transform: scale3d(1.01, 1.01, 1.01)
542
+ rotate3d(var(--limel-3d-hover-effect-rotate3d));
543
+ }
544
+ &:focus-visible {
545
+ outline: none;
546
+ transform: scale3d(1.01, 1.01, 1.01);
547
+ }
548
+ }
549
+
550
+ @mixin the-3d-element--clickable {
551
+ cursor: pointer;
552
+ box-shadow: var(--button-shadow-normal);
553
+
554
+ &:hover,
555
+ &:focus-visible {
556
+ // seems repetitive. But it's required for some scenarios, like for info tiles.
557
+ box-shadow: var(--button-shadow-hovered), var(--shadow-depth-16);
558
+ }
559
+
560
+ &:active {
561
+ transform: scale3d(1, 1, 1) rotate3d(0, 0, 0, 0deg);
562
+ box-shadow: var(--button-shadow-pressed);
563
+ }
564
+
565
+ &:focus-visible {
566
+ box-shadow: var(--shadow-depth-8-focused), var(--button-shadow-hovered);
567
+ }
568
+
569
+ &:focus-visible:active {
570
+ box-shadow: var(--shadow-depth-8-focused), var(--button-shadow-pressed);
571
+ }
572
+ }
@@ -0,0 +1,157 @@
1
+ /* eslint-disable tsdoc/syntax */
2
+ /**
3
+ * Utility functions for creating a 3D tilt hover effect.
4
+ *
5
+ * This module provides functions to enable a 3D tilt effect for consumer components,
6
+ * allowing elements to visually follow the cursor's position and tilt towards it.
7
+ * It also includes a glow effect for added interactivity.
8
+ *
9
+ * ## Usage
10
+ *
11
+ * 1. **Import the utility**:
12
+ *
13
+ * ```tsx
14
+ * import { getMouseEventHandlers } from './path/to/3d-tilt-hover-effect';
15
+ * ```
16
+ *
17
+ * 2. **Define the structure of your component**:
18
+ *
19
+ * To enable the 3D tilt effect, the host element of your component should act as
20
+ * the "parent-of-the-3d-element", and a nested child element should act as
21
+ * "the-3d-element" (the interactive element). This structure is necessary
22
+ * to properly isolate the 3D transformations and maintain visual fidelity.
23
+ *
24
+ * For example:
25
+ *
26
+ * ```tsx
27
+ * <Host>
28
+ * <section class="the-3d-element">
29
+ * <!-- Your component content -->
30
+ * </section>
31
+ * </Host>
32
+ * ```
33
+ *
34
+ * Apply the required SCSS mixins to these elements:
35
+ *
36
+ * - **On the host element**:
37
+ * ```scss
38
+ * @include parent-of-the-3d-element;
39
+ * ```
40
+ * - **On the nested "interactive" element**:
41
+ * ```scss
42
+ * @include the-3d-element;
43
+ * ```
44
+ * - **For clickable interactive elements**:
45
+ * ```scss
46
+ * @include the-3d-element--clickable;
47
+ * ```
48
+ * - **For the glow effect**:
49
+ * Add a `<div class="limel-3d-hover-effect-glow" />` inside "the-3d-element",
50
+ * and use the following SCSS mixin:
51
+ * ```scss
52
+ * @include limel-3d-hover-effect-glow($selector, $border-radius);
53
+ * ```
54
+ *
55
+ * 3. **Initialize in your component**:
56
+ *
57
+ * Use `getMouseEventHandlers()` to attach the required mouse event listeners
58
+ * to the "interactive element" (`the-3d-element`). For example:
59
+ *
60
+ * ```tsx
61
+ * @Element()
62
+ * private host: HTMLElement;
63
+ *
64
+ * private handleMouseEnter: () => void;
65
+ * private handleMouseLeave: () => void;
66
+ *
67
+ * public componentWillLoad() {
68
+ * const { handleMouseEnter, handleMouseLeave } = getMouseEventHandlers(
69
+ * this.host.querySelector('.the-3d-element'),
70
+ * );
71
+ * this.handleMouseEnter = handleMouseEnter;
72
+ * this.handleMouseLeave = handleMouseLeave;
73
+ * }
74
+ * ```
75
+ *
76
+ * 4. **Attach event handlers in your render method**:
77
+ *
78
+ * ```tsx
79
+ * public render() {
80
+ * return (
81
+ * <Host>
82
+ * <section
83
+ * class="the-3d-element"
84
+ * onMouseEnter={this.handleMouseEnter}
85
+ * onMouseLeave={this.handleMouseLeave}
86
+ * >
87
+ * <!-- Your component content -->
88
+ * <div class="limel-3d-hover-effect-glow" />
89
+ * </section>
90
+ * </Host>
91
+ * );
92
+ * }
93
+ * ```
94
+ *
95
+ * ## Styling Notes
96
+ *
97
+ * - The host element (`parent-of-the-3d-element`) must have these styles:
98
+ * ```scss
99
+ * @include parent-of-the-3d-element;
100
+ * ```
101
+ * - The nested "interactive element" (`the-3d-element`) should have:
102
+ * ```scss
103
+ * @include the-3d-element;
104
+ * ```
105
+ * - For components like Card or Info Tile, using a nested "interactive element"
106
+ * is the only way to achieve the 3D effect, as the host serves as the parent
107
+ * and must maintain proper isolation for the effect.
108
+ */
109
+ /* eslint-enable tsdoc/syntax */
110
+ export const MOUSE_SCALE_FACTOR = 100;
111
+ export const SCALING_BASE = 50;
112
+ export const ROTATION_DEGREE_MULTIPLIER = 1.6;
113
+ export const GLOW_POSITION_MULTIPLIER = 2;
114
+ export const CENTER_DIVISOR = 2;
115
+ export const tiltFollowingTheCursor = (the3dElementBounds, element) => (e) => {
116
+ const mouseX = e.clientX;
117
+ const mouseY = e.clientY;
118
+ const leftX = mouseX - the3dElementBounds.x;
119
+ const topY = mouseY - the3dElementBounds.y;
120
+ const center = {
121
+ x: leftX - the3dElementBounds.width / CENTER_DIVISOR,
122
+ y: topY - the3dElementBounds.height / CENTER_DIVISOR,
123
+ };
124
+ const distance = Math.sqrt(center.x ** CENTER_DIVISOR + center.y ** CENTER_DIVISOR);
125
+ const scalingFactor = Math.sqrt(Math.min(the3dElementBounds.width, the3dElementBounds.height) /
126
+ SCALING_BASE);
127
+ const rotate3d = `
128
+ ${center.y / (MOUSE_SCALE_FACTOR * scalingFactor)},
129
+ ${-center.x / (MOUSE_SCALE_FACTOR * scalingFactor)},
130
+ 0,
131
+ ${(Math.log(distance) * ROTATION_DEGREE_MULTIPLIER) / scalingFactor}deg
132
+ `;
133
+ element.style.setProperty('--limel-3d-hover-effect-rotate3d', rotate3d);
134
+ const glowPosition = `
135
+ ${center.x * GLOW_POSITION_MULTIPLIER + the3dElementBounds.width / CENTER_DIVISOR}px
136
+ ${center.y * GLOW_POSITION_MULTIPLIER + the3dElementBounds.height / CENTER_DIVISOR}px
137
+ `;
138
+ element.style.setProperty('--limel-3d-hover-effect-glow-position', glowPosition);
139
+ };
140
+ export const getMouseEventHandlers = (element) => {
141
+ let tiltCallback;
142
+ const handleMouseEnter = () => {
143
+ const bounds = element.getBoundingClientRect();
144
+ tiltCallback = tiltFollowingTheCursor(bounds, element);
145
+ document.addEventListener('mousemove', tiltCallback);
146
+ };
147
+ const handleMouseLeave = () => {
148
+ document.removeEventListener('mousemove', tiltCallback);
149
+ element.style.removeProperty('--limel-3d-hover-effect-rotate3d');
150
+ element.style.removeProperty('--limel-3d-hover-effect-glow-position');
151
+ };
152
+ return {
153
+ handleMouseEnter: handleMouseEnter,
154
+ handleMouseLeave: handleMouseLeave,
155
+ };
156
+ };
157
+ //# sourceMappingURL=3d-tilt-hover-effect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"3d-tilt-hover-effect.js","sourceRoot":"","sources":["../../src/util/3d-tilt-hover-effect.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable tsdoc/syntax */\n/**\n * Utility functions for creating a 3D tilt hover effect.\n *\n * This module provides functions to enable a 3D tilt effect for consumer components,\n * allowing elements to visually follow the cursor's position and tilt towards it.\n * It also includes a glow effect for added interactivity.\n *\n * ## Usage\n *\n * 1. **Import the utility**:\n *\n * ```tsx\n * import { getMouseEventHandlers } from './path/to/3d-tilt-hover-effect';\n * ```\n *\n * 2. **Define the structure of your component**:\n *\n * To enable the 3D tilt effect, the host element of your component should act as\n * the \"parent-of-the-3d-element\", and a nested child element should act as\n * \"the-3d-element\" (the interactive element). This structure is necessary\n * to properly isolate the 3D transformations and maintain visual fidelity.\n *\n * For example:\n *\n * ```tsx\n * <Host>\n * <section class=\"the-3d-element\">\n * <!-- Your component content -->\n * </section>\n * </Host>\n * ```\n *\n * Apply the required SCSS mixins to these elements:\n *\n * - **On the host element**:\n * ```scss\n * @include parent-of-the-3d-element;\n * ```\n * - **On the nested \"interactive\" element**:\n * ```scss\n * @include the-3d-element;\n * ```\n * - **For clickable interactive elements**:\n * ```scss\n * @include the-3d-element--clickable;\n * ```\n * - **For the glow effect**:\n * Add a `<div class=\"limel-3d-hover-effect-glow\" />` inside \"the-3d-element\",\n * and use the following SCSS mixin:\n * ```scss\n * @include limel-3d-hover-effect-glow($selector, $border-radius);\n * ```\n *\n * 3. **Initialize in your component**:\n *\n * Use `getMouseEventHandlers()` to attach the required mouse event listeners\n * to the \"interactive element\" (`the-3d-element`). For example:\n *\n * ```tsx\n * @Element()\n * private host: HTMLElement;\n *\n * private handleMouseEnter: () => void;\n * private handleMouseLeave: () => void;\n *\n * public componentWillLoad() {\n * const { handleMouseEnter, handleMouseLeave } = getMouseEventHandlers(\n * this.host.querySelector('.the-3d-element'),\n * );\n * this.handleMouseEnter = handleMouseEnter;\n * this.handleMouseLeave = handleMouseLeave;\n * }\n * ```\n *\n * 4. **Attach event handlers in your render method**:\n *\n * ```tsx\n * public render() {\n * return (\n * <Host>\n * <section\n * class=\"the-3d-element\"\n * onMouseEnter={this.handleMouseEnter}\n * onMouseLeave={this.handleMouseLeave}\n * >\n * <!-- Your component content -->\n * <div class=\"limel-3d-hover-effect-glow\" />\n * </section>\n * </Host>\n * );\n * }\n * ```\n *\n * ## Styling Notes\n *\n * - The host element (`parent-of-the-3d-element`) must have these styles:\n * ```scss\n * @include parent-of-the-3d-element;\n * ```\n * - The nested \"interactive element\" (`the-3d-element`) should have:\n * ```scss\n * @include the-3d-element;\n * ```\n * - For components like Card or Info Tile, using a nested \"interactive element\"\n * is the only way to achieve the 3D effect, as the host serves as the parent\n * and must maintain proper isolation for the effect.\n */\n/* eslint-enable tsdoc/syntax */\n\nexport const MOUSE_SCALE_FACTOR = 100;\nexport const SCALING_BASE = 50;\nexport const ROTATION_DEGREE_MULTIPLIER = 1.6;\nexport const GLOW_POSITION_MULTIPLIER = 2;\nexport const CENTER_DIVISOR = 2;\n\nexport const tiltFollowingTheCursor =\n (the3dElementBounds: DOMRect, element: HTMLElement) => (e: MouseEvent) => {\n const mouseX = e.clientX;\n const mouseY = e.clientY;\n const leftX = mouseX - the3dElementBounds.x;\n const topY = mouseY - the3dElementBounds.y;\n const center = {\n x: leftX - the3dElementBounds.width / CENTER_DIVISOR,\n y: topY - the3dElementBounds.height / CENTER_DIVISOR,\n };\n const distance = Math.sqrt(\n center.x ** CENTER_DIVISOR + center.y ** CENTER_DIVISOR,\n );\n\n const scalingFactor = Math.sqrt(\n Math.min(the3dElementBounds.width, the3dElementBounds.height) /\n SCALING_BASE,\n );\n\n const rotate3d = `\n ${center.y / (MOUSE_SCALE_FACTOR * scalingFactor)},\n ${-center.x / (MOUSE_SCALE_FACTOR * scalingFactor)},\n 0,\n ${(Math.log(distance) * ROTATION_DEGREE_MULTIPLIER) / scalingFactor}deg\n `;\n element.style.setProperty('--limel-3d-hover-effect-rotate3d', rotate3d);\n\n const glowPosition = `\n ${center.x * GLOW_POSITION_MULTIPLIER + the3dElementBounds.width / CENTER_DIVISOR}px\n ${center.y * GLOW_POSITION_MULTIPLIER + the3dElementBounds.height / CENTER_DIVISOR}px\n `;\n element.style.setProperty(\n '--limel-3d-hover-effect-glow-position',\n glowPosition,\n );\n };\n\nexport const getMouseEventHandlers = (element: HTMLElement) => {\n let tiltCallback: (e: MouseEvent) => void;\n\n const handleMouseEnter = () => {\n const bounds = element.getBoundingClientRect();\n tiltCallback = tiltFollowingTheCursor(bounds, element);\n document.addEventListener('mousemove', tiltCallback);\n };\n\n const handleMouseLeave = () => {\n document.removeEventListener('mousemove', tiltCallback);\n element.style.removeProperty('--limel-3d-hover-effect-rotate3d');\n element.style.removeProperty('--limel-3d-hover-effect-glow-position');\n };\n\n return {\n handleMouseEnter: handleMouseEnter,\n handleMouseLeave: handleMouseLeave,\n };\n};\n"]}