@studiometa/ui 1.0.0-rc.6 → 1.0.0-rc.7
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.
- package/Figure/Figure.twig +10 -0
- package/Sticky/Sticky.d.ts +4 -12
- package/Sticky/Sticky.js +8 -2
- package/Sticky/Sticky.js.map +2 -2
- package/Sticky/Sticky.twig +19 -7
- package/package.json +1 -1
package/Figure/Figure.twig
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
* @param string $alt
|
|
12
12
|
* @param string $caption
|
|
13
13
|
* @param boolean $lazy
|
|
14
|
+
* @param boolean $lazy_fallback
|
|
15
|
+
* Define if a fallback image should be added for SEO purpose.
|
|
14
16
|
* @param 'cover'|'contain'|'fill'|'none' $fit
|
|
15
17
|
* Define how the image will fit.
|
|
16
18
|
* @param boolean $absolute
|
|
@@ -114,6 +116,14 @@
|
|
|
114
116
|
<figure {{ html_attributes(attributes) }}>
|
|
115
117
|
<div {{ html_attributes(inner_attributes) }}>
|
|
116
118
|
<img {{ html_attributes(img_attributes) }} />
|
|
119
|
+
{% if lazy and (lazy_fallback ?? false) %}
|
|
120
|
+
{% set img_noscript_attributes = img_attributes|twig_toolkit_without('data_src', 'data_ref')|merge({
|
|
121
|
+
src: img_attributes.data_src,
|
|
122
|
+
}) %}
|
|
123
|
+
<noscript>
|
|
124
|
+
<img {{ html_attributes(img_noscript_attributes) }}>
|
|
125
|
+
</noscript>
|
|
126
|
+
{% endif %}
|
|
117
127
|
</div>
|
|
118
128
|
{% if caption is defined %}
|
|
119
129
|
{% block caption %}
|
package/Sticky/Sticky.d.ts
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
1
|
import { Base } from '@studiometa/js-toolkit';
|
|
2
2
|
import type { BaseProps, BaseConfig } from '@studiometa/js-toolkit';
|
|
3
3
|
import { Sentinel } from '../Sentinel/index.js';
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {object} StickyRefs
|
|
6
|
-
* @property {HTMLElement} inner
|
|
7
|
-
* @property {HTMLElement} sentinelRef
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* @typedef {object} StickyPrivateInterface
|
|
11
|
-
* @property {StickyRefs} $refs
|
|
12
|
-
* @property {{ zIndex: number, hideWhenUp: boolean, hideWhenDown: boolean }} $options
|
|
13
|
-
* @property {{ Sentinel: Sentinel[] }} $children
|
|
14
|
-
*/
|
|
15
4
|
export interface StickyProps extends BaseProps {
|
|
16
5
|
$refs: {
|
|
17
6
|
inner: HTMLElement;
|
|
18
|
-
sentinelRef: HTMLElement;
|
|
19
7
|
};
|
|
20
8
|
$options: {
|
|
21
9
|
zIndex: number;
|
|
@@ -54,6 +42,10 @@ export declare class Sticky<T extends BaseProps = BaseProps> extends Base<T & St
|
|
|
54
42
|
* Get instances as array.
|
|
55
43
|
*/
|
|
56
44
|
get instances(): Sticky[];
|
|
45
|
+
/**
|
|
46
|
+
* Get the sentinel instance.
|
|
47
|
+
*/
|
|
48
|
+
get sentinel(): Sentinel;
|
|
57
49
|
/**
|
|
58
50
|
* Mounted hook.
|
|
59
51
|
*/
|
package/Sticky/Sticky.js
CHANGED
|
@@ -6,7 +6,7 @@ class Sticky extends Base {
|
|
|
6
6
|
*/
|
|
7
7
|
static config = {
|
|
8
8
|
name: "Sticky",
|
|
9
|
-
refs: ["inner"
|
|
9
|
+
refs: ["inner"],
|
|
10
10
|
components: {
|
|
11
11
|
Sentinel
|
|
12
12
|
},
|
|
@@ -44,6 +44,12 @@ class Sticky extends Base {
|
|
|
44
44
|
get instances() {
|
|
45
45
|
return Array.from(Sticky.instances);
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the sentinel instance.
|
|
49
|
+
*/
|
|
50
|
+
get sentinel() {
|
|
51
|
+
return this.$children.Sentinel[0];
|
|
52
|
+
}
|
|
47
53
|
/**
|
|
48
54
|
* Mounted hook.
|
|
49
55
|
*/
|
|
@@ -117,7 +123,7 @@ class Sticky extends Base {
|
|
|
117
123
|
// Test each instance sticky context against the current element
|
|
118
124
|
(instance) => this.closestRelativeElement(instance.$el).contains(this.$el)
|
|
119
125
|
).reduce((acc, instance) => acc + instance.$el.offsetHeight, 0);
|
|
120
|
-
this.$
|
|
126
|
+
this.sentinel.$el.style.height = `${height + 1}px`;
|
|
121
127
|
this.$el.style.top = `${height}px`;
|
|
122
128
|
this.$el.style.zIndex = String(this.$options.zIndex - index);
|
|
123
129
|
}
|
package/Sticky/Sticky.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../packages/ui/Sticky/Sticky.ts"],
|
|
4
|
-
"sourcesContent": ["import { Base } from '@studiometa/js-toolkit';\nimport type { BaseProps, BaseConfig } from '@studiometa/js-toolkit';\nimport { Sentinel } from '../Sentinel/index.js';\n\
|
|
5
|
-
"mappings": "AAAA,SAAS,YAAY;AAErB,SAAS,gBAAgB;
|
|
4
|
+
"sourcesContent": ["import { Base } from '@studiometa/js-toolkit';\nimport type { BaseProps, BaseConfig } from '@studiometa/js-toolkit';\nimport { Sentinel } from '../Sentinel/index.js';\n\nexport interface StickyProps extends BaseProps {\n $refs: {\n inner: HTMLElement;\n };\n $options: {\n zIndex: number;\n hideWhenUp: boolean;\n hideWhenDown: boolean;\n };\n $children: {\n Sentinel: Sentinel[];\n };\n}\n\n/**\n * Sticky class.\n */\nexport class Sticky<T extends BaseProps = BaseProps> extends Base<T & StickyProps> {\n /**\n * Config.\n */\n static config: BaseConfig = {\n name: 'Sticky',\n refs: ['inner'],\n components: {\n Sentinel,\n },\n options: {\n zIndex: {\n type: Number,\n default: 100,\n },\n hideWhenUp: Boolean,\n hideWhenDown: Boolean,\n },\n };\n\n /**\n * Holder for all instances.\n */\n // eslint-disable-next-line no-use-before-define\n static instances: Set<Sticky> = new Set();\n\n /**\n * Is the component sticky?\n */\n isSticky = false;\n\n /**\n * Is the component visible?\n */\n isVisible = true;\n\n /**\n * Set the Y value.\n */\n set y(value: number) {\n this.$refs.inner.style.transform = `translateY(${value}px) translateZ(0px)`;\n }\n\n /**\n * Get instances as array.\n */\n get instances(): Sticky[] {\n return Array.from(Sticky.instances);\n }\n\n /**\n * Get the sentinel instance.\n */\n get sentinel(): Sentinel {\n return this.$children.Sentinel[0];\n }\n\n /**\n * Mounted hook.\n */\n mounted() {\n Sticky.instances.add(this);\n this.setSentinelSize();\n }\n\n /**\n * Resized hook.\n */\n resized() {\n this.setSentinelSize();\n }\n\n /**\n * Destroyed hook.\n */\n destroyed() {\n Sticky.instances.delete(this);\n }\n\n /**\n * Scrolled hook.\n */\n scrolled(props) {\n if (!this.isSticky || props.y === props.last.y) {\n return;\n }\n\n if (\n (props.direction.y === 'DOWN' && this.$options.hideWhenDown) ||\n (props.direction.y === 'UP' && this.$options.hideWhenUp)\n ) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Listen to the sentinel's `intersected` event to set the `isSticky` value.\n * @param {IntersectionObserverEntry[]} entries\n * @returns {void}\n */\n onSentinelIntersected({ args: [[entry]] }: { args: [IntersectionObserverEntry[]] }) {\n this.isSticky = entry.isIntersecting && entry.boundingClientRect.y < 0;\n this.setPosition();\n }\n\n /**\n * Hide the sticky component when another one is sticky.\n */\n hide() {\n if (!this.isVisible) {\n return;\n }\n\n this.isVisible = false;\n this.$el.classList.add('pointer-events-none');\n\n this.instances.forEach((instance, index) => instance.setPosition(index));\n }\n\n /**\n * Show the sticky component when the other one is not sticky anymore.\n */\n show() {\n if (this.isVisible) {\n return;\n }\n\n this.isVisible = true;\n this.$el.classList.remove('pointer-events-none');\n this.instances.forEach((instance, index) => instance.setPosition(index));\n }\n\n /**\n * Set the sentinel height based on the previous instances.\n */\n setSentinelSize() {\n const { instances } = this;\n const index = instances.indexOf(this);\n const height = instances\n .slice(0, index)\n .filter(\n // Test each instance sticky context against the current element\n (instance) => this.closestRelativeElement(instance.$el).contains(this.$el),\n )\n .reduce((acc, instance) => acc + instance.$el.offsetHeight, 0);\n\n this.sentinel.$el.style.height = `${height + 1}px`;\n this.$el.style.top = `${height}px`;\n this.$el.style.zIndex = String(this.$options.zIndex - index);\n }\n\n /**\n * Set the component's position.\n * @param {number} [index] The instance index in all the pages' instances.\n * @returns {void}\n */\n setPosition(index?: number) {\n if (!this.isSticky) {\n this.y = 0;\n return;\n }\n\n const { instances } = this;\n\n // eslint-disable-next-line no-param-reassign\n index = index ?? instances.indexOf(this);\n\n this.y = instances\n .slice(0, index)\n .filter((instance) => instance.isSticky && !instance.isVisible)\n .reduce<number>(\n (y: number, instance) => y - instance.$refs.inner.offsetHeight,\n this.isVisible ? 0 : this.$refs.inner.offsetHeight * -1,\n ) as number;\n }\n\n /**\n * Find the first parent which has a relative position.\n */\n closestRelativeElement(element: HTMLElement) {\n let parent = element.parentElement;\n\n while (getComputedStyle(parent).position !== 'relative' && parent.parentElement) {\n parent = parent.parentElement;\n }\n\n return parent;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/Sticky/Sticky.twig
CHANGED
|
@@ -13,16 +13,28 @@
|
|
|
13
13
|
*/
|
|
14
14
|
#}
|
|
15
15
|
|
|
16
|
-
{% set
|
|
17
|
-
|
|
16
|
+
{% set attributes =
|
|
17
|
+
merge_html_attributes(
|
|
18
|
+
attr ?? null,
|
|
19
|
+
{
|
|
20
|
+
data_component: 'Sticky',
|
|
21
|
+
class: 'z-10 sticky top-0 w-full'
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
%}
|
|
18
25
|
|
|
19
|
-
{% set
|
|
20
|
-
|
|
26
|
+
{% set inner_attributes =
|
|
27
|
+
merge_html_attributes(
|
|
28
|
+
inner_attr ?? null,
|
|
29
|
+
{
|
|
30
|
+
data_ref: 'inner',
|
|
31
|
+
class: 'transition duration-500 ease-out-expo'
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
%}
|
|
21
35
|
|
|
22
36
|
<div {{ html_attributes(attributes) }}>
|
|
23
|
-
<div data-
|
|
24
|
-
data-component="Sentinel"
|
|
25
|
-
class="absolute bottom-full w-full h-px pointer-events-none"></div>
|
|
37
|
+
<div data-component="Sentinel" class="absolute bottom-full w-full h-px pointer-events-none"></div>
|
|
26
38
|
<div {{ html_attributes(inner_attributes) }}>
|
|
27
39
|
{% block content %}
|
|
28
40
|
{{ content ?? '' }}
|