@inizioevoke/astro-core 1.6.5 → 2.0.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 (32) hide show
  1. package/package.json +3 -5
  2. package/src/components/FlipCard/FlipCard.ts +15 -9
  3. package/src/components/ISI/{RightISI.astro → Right/RightISI.astro} +16 -9
  4. package/src/components/ISI/Right/RightISI.css +61 -0
  5. package/src/components/ISI/{RightISI.md → Right/RightISI.md} +0 -1
  6. package/src/components/ISI/Right/RightISI.ts +78 -0
  7. package/src/components/ISI/Right/index.ts +1 -0
  8. package/src/components/ISI/index.ts +5 -0
  9. package/src/components/Modal/Modal.astro +11 -5
  10. package/src/components/Modal/Modal.css +49 -39
  11. package/src/components/Modal/Modal.ts +186 -169
  12. package/src/components/PdfViewer/PdfViewer.astro +6 -3
  13. package/src/components/PdfViewer/PdfViewer.css +5 -3
  14. package/src/components/PdfViewer/PdfViewer.ts +226 -198
  15. package/src/components/ScrollContainer/ScrollContainer.ts +23 -2
  16. package/src/components/index.ts +1 -0
  17. package/src/lib/gestures/index.ts +2 -0
  18. package/src/lib/gestures/pinch.ts +66 -0
  19. package/src/lib/gestures/swipe.ts +153 -0
  20. package/src/lib/index.ts +2 -0
  21. package/src/components/ISI/RightISI.css +0 -31
  22. package/src/components/ISI/RightISI.ts +0 -27
  23. package/src/components/Modal/v2/Modal.astro +0 -42
  24. package/src/components/Modal/v2/Modal.css +0 -155
  25. package/src/components/Modal/v2/Modal.ts +0 -219
  26. package/src/components/Modal/v2/ModalOverlay.astro +0 -14
  27. package/src/components/Modal/v2/ModalTrigger.astro +0 -29
  28. package/src/components/Modal/v2/index.ts +0 -1
  29. package/src/components/ScrollContainer/archive-20260417.ts +0 -150
  30. package/src/components/v2.ts +0 -3
  31. package/src/lib/swipe.ts +0 -109
  32. package/src/lib/v2.ts +0 -1
@@ -0,0 +1,153 @@
1
+ export type SwipeDirection = 'left' | 'right' | 'left-right' | 'up' | 'down' | 'up-down';
2
+ export type SwipeThreshold = '1/4' | '1/3' | '1/2' | number;
3
+
4
+ export interface OnSwipeHandlerArgs {
5
+ direction: SwipeDirection;
6
+ threshold: number;
7
+ distance: {
8
+ x: number;
9
+ y: number;
10
+ },
11
+ duration: number;
12
+ }
13
+ export type OnSwipeHandler = (args: OnSwipeHandlerArgs) => void;
14
+
15
+ export interface SwipeController {
16
+ enable: () => void;
17
+ disable: () => void;
18
+ dispose: () => void;
19
+ }
20
+
21
+ export function createSwipeListener(direction: SwipeDirection, threshold: SwipeThreshold, handler: OnSwipeHandler): SwipeController {
22
+ const swipeThreshold: number = typeof threshold == 'number' ? threshold : (() => {
23
+ const ratios: Record<string, number> = { '1/4': 0.25, '1/3': 0.333, '1/2': 0.5 };
24
+ switch (direction) {
25
+ case 'up':
26
+ case 'down':
27
+ case 'up-down':
28
+ return Math.round(window.innerHeight * (ratios[threshold] ?? ratios['1/3'])); // screen.height
29
+ default:
30
+ return Math.round(window.innerWidth * (ratios[threshold] ?? ratios['1/3'])); // screen.width
31
+ }
32
+ })();
33
+
34
+ let listening = false;
35
+ let x: number = NaN;
36
+ let y: number = NaN;
37
+ let start: number = NaN;
38
+
39
+ const isUp = (deltaX: number, deltaY: number) => {
40
+ return Math.abs(deltaY) >= swipeThreshold && Math.abs(deltaX) < swipeThreshold && deltaY > 0;
41
+ }
42
+ const isDown = (deltaX: number, deltaY: number) => {
43
+ return Math.abs(deltaY) >= swipeThreshold && Math.abs(deltaX) < swipeThreshold && deltaY < 0;
44
+ }
45
+ const isLeft = (deltaX: number, deltaY: number) => {
46
+ return Math.abs(deltaX) >= swipeThreshold && Math.abs(deltaY) < swipeThreshold && deltaX > 0;
47
+ }
48
+ const isRight = (deltaX: number, deltaY: number) => {
49
+ return Math.abs(deltaX) >= swipeThreshold && Math.abs(deltaY) < swipeThreshold && deltaX < 0;
50
+ }
51
+
52
+ const handleSwipe = (deltaX: number, deltaY: number, duration: number) => {
53
+ let swipeDirection: SwipeDirection | undefined = undefined;
54
+ switch (direction) {
55
+ case 'up':
56
+ if (isUp(deltaX, deltaY)) {
57
+ swipeDirection = 'up';
58
+ }
59
+ break;
60
+ case 'down':
61
+ if (isDown(deltaX, deltaY)) {
62
+ swipeDirection = 'down';
63
+ }
64
+ break;
65
+ case 'up-down':
66
+ if (isUp(deltaX, deltaY)) {
67
+ swipeDirection = 'up';
68
+ } else if (isDown(deltaX, deltaY)) {
69
+ swipeDirection = 'down';
70
+ }
71
+ break;
72
+ case 'left':
73
+ if (isLeft(deltaX, deltaY)) {
74
+ swipeDirection = 'left';
75
+ }
76
+ break;
77
+ case 'right':
78
+ if (isRight(deltaX, deltaY)) {
79
+ swipeDirection = 'right';
80
+ }
81
+ break;
82
+ case 'left-right':
83
+ if (isLeft(deltaX, deltaY)) {
84
+ swipeDirection = 'left';
85
+ } else if (isRight(deltaX, deltaY)) {
86
+ swipeDirection = 'right';
87
+ }
88
+ break;
89
+ }
90
+ if (swipeDirection) {
91
+ try {
92
+ handler({ direction: swipeDirection, threshold: swipeThreshold, distance: { x: deltaX, y: deltaY }, duration});
93
+ } catch (err) {
94
+ console.error(err);
95
+ }
96
+ }
97
+ }
98
+
99
+ const touchstart = (e: TouchEvent) => {
100
+ if (!listening) return;
101
+ if (e.touches.length === 1 && isNaN(x)) {
102
+ start = performance.now();
103
+ x = e.touches[0].clientX;
104
+ y = e.touches[0].clientY;
105
+ } else {
106
+ start = NaN;
107
+ x = NaN;
108
+ y = NaN;
109
+ }
110
+ };
111
+
112
+ const touchcancel = () => {
113
+ x = NaN;
114
+ y = NaN;
115
+ start = NaN;
116
+ };
117
+
118
+ const touchend = (e: TouchEvent) => {
119
+ if (!listening) return;
120
+ if (e.changedTouches.length === 1 && !isNaN(x) && !isNaN(y)) {
121
+ const deltaX = x - e.changedTouches[0].clientX;
122
+ const deltaY = y - e.changedTouches[0].clientY;
123
+ handleSwipe(deltaX, deltaY, performance.now() - start);
124
+ x = NaN;
125
+ y = NaN;
126
+ start = NaN;
127
+ }
128
+ };
129
+
130
+ const enable = () => {
131
+ if (!listening) {
132
+ listening = true;
133
+ window.addEventListener('touchstart', touchstart, { passive: true });
134
+ window.addEventListener('touchend', touchend, { passive: true });
135
+ window.addEventListener('touchcancel', touchcancel, { passive: true });
136
+ }
137
+ };
138
+
139
+ const disable = () => {
140
+ listening = false;
141
+ window.removeEventListener('touchstart', touchstart);
142
+ window.removeEventListener('touchend', touchend);
143
+ window.removeEventListener('touchcancel', touchcancel);
144
+ };
145
+
146
+ enable();
147
+
148
+ return {
149
+ enable,
150
+ disable,
151
+ dispose: disable
152
+ };
153
+ }
package/src/lib/index.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * as FlipCard from '../components/FlipCard/FlipCard';
2
+ export * as ISI from '../components/ISI/index';
3
+ export * as gestures from './gestures';
2
4
  export * as Modal from '../components/Modal/Modal';
3
5
  export * as PdfViewer from '../components/PdfViewer/PdfViewer';
4
6
  export * as ScrollContainer from '../components/ScrollContainer/ScrollContainer';
@@ -1,31 +0,0 @@
1
- :root {
2
- --evo-isi-width: 25vw;
3
- --evo-isi-width-expanded: 100vw;
4
- --evo-isi-height: 100vh;
5
- --evo-isi-header-height: 0px;
6
- --evo-isi-footer-height: 0px;
7
- }
8
- .evo-isi {
9
- position: fixed;
10
- right: 0;
11
- top: 0;
12
- display: block;
13
- width: var(--evo-isi-width);
14
- height: var(--evo-isi-height);
15
- overflow: hidden;
16
- z-index: 99;
17
- background-color: #ffffff;
18
-
19
- transform-origin: right top;
20
- transition-property: width;
21
- transition-duration: 500ms;
22
- transition-timing-function: ease-in-out;
23
-
24
- .evo-isi-wrapper {
25
- .evo-isi-text {
26
- .evo-scroll-container {
27
- /* height: calc(var(--evo-isi-height) - var(--evo-isi-header-height) - var(--evo-isi-footer-height)) */
28
- }
29
- }
30
- }
31
- }
@@ -1,27 +0,0 @@
1
- import * as ScrollContainer from '../ScrollContainer/ScrollContainer';
2
-
3
- const isi = document.querySelector('.evo-isi') as HTMLElement;
4
- const isiHeader = isi.querySelector<HTMLElement>('.evo-isi-header');
5
- const isiFooter = isi.querySelector<HTMLElement>('.evo-isi-footer');
6
- const isiText = isi.querySelector('.evo-isi-text') as HTMLElement;
7
-
8
- export function resize() {
9
- if (isi) {
10
- const isiStyle = getComputedStyle(isi);
11
- const isiHeight = parseInt(isiStyle.height);
12
- const headerHeight = isiHeader ? parseInt(getComputedStyle(isiHeader).height) : 0;
13
- const footerHeight = isiFooter ? parseInt(getComputedStyle(isiFooter).height) : 0;
14
-
15
- const isiTextStyle = getComputedStyle(isiText);
16
- const textPadTop = parseInt(isiTextStyle.paddingTop);
17
- const textPadBot = parseInt(isiTextStyle.paddingBottom);
18
-
19
- const scrollContainer = ScrollContainer.getScrollContainer(isi.querySelector('.evo-isi-text .evo-scroll-container') as HTMLElement);
20
- if (scrollContainer) {
21
- const height = isiHeight - headerHeight - footerHeight - textPadTop - textPadBot;
22
- ScrollContainer.resize(scrollContainer, { height });
23
- }
24
- }
25
- }
26
- addEventListener('load', resize, { passive: true });
27
- window.addEventListener('resize', resize, { passive: true });
@@ -1,42 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from 'astro/types';
3
- import './Modal.css';
4
-
5
- interface Props extends HTMLAttributes<'div'> {
6
- id: string;
7
- closeButton?: 'default' | 'minimal' | 'none' | 'false' | false;
8
- closeButtonAtts?: Record<string, string>;
9
- }
10
-
11
- const {
12
- id,
13
- closeButton = 'default',
14
- closeButtonAtts,
15
- ...rest
16
- } = Astro.props;
17
-
18
- const attrs = {...rest};
19
- const cssClass = attrs['class'] ?? '';
20
-
21
- ['class'].forEach((a) => {
22
- delete attrs[a as keyof typeof attrs];
23
- });
24
-
25
- const showCloseButton = closeButton !== false && closeButton !== 'false' && closeButton !== 'none';
26
- const closeButtonCssClassList = ['evo-modal-close', 'evo-modal-action-hide'];
27
- if (showCloseButton) {
28
- closeButtonCssClassList.push(`evo-modal-theme-${closeButton}`)
29
- }
30
-
31
- ---
32
- <evo-modal id={id} class:list={['evo-modal', cssClass]} {...attrs}>
33
- {showCloseButton && <button class:list={closeButtonCssClassList} {...closeButtonAtts}><span class="evo-modal-x"><slot name="close">X</slot></span></button>}
34
- <slot name="outer" />
35
- <div class="evo-modal-wrapper">
36
- <slot />
37
- </div>
38
- </evo-modal>
39
-
40
- <script>
41
- import './Modal';
42
- </script>
@@ -1,155 +0,0 @@
1
-
2
- @layer inizioevoke-astro-components {
3
- :root {
4
- --evo-modal-viewport-width: 100vw;
5
- --evo-modal-viewport-height: 100vh;
6
- --evo-modal-position: absolute;
7
- --evo-modal-width: 800px;
8
- --evo-modal-height: 450px;
9
- --evo-modal-animation-duration: 300ms;
10
- --evo-modal-z-index: 99;
11
- --evo-modal-overlay-blur: 2px;
12
- }
13
-
14
- .evo-modal-overlay {
15
- position: fixed;
16
- left: 0;
17
- top: 0;
18
- display: none;
19
- opacity: 0;
20
- width: 100%;
21
- height: 100%;
22
- backdrop-filter: blur(var(--evo-modal-overlay-blur));
23
- background-color: rgba(0,0,0,0.66);
24
- z-index: calc(var(--evo-modal-z-index) - 1);
25
- animation-duration: var(--evo-modal-animation-duration);
26
- animation-iteration-count: 1;
27
- animation-timing-function: linear;
28
- animation-fill-mode: forwards;
29
- }
30
-
31
- evo-modal {
32
- position: var(--evo-modal-position);
33
- left: calc((var(--evo-modal-viewport-width) - var(--evo-modal-width)) / 2);
34
- top: calc((var(--evo-modal-viewport-height) - var(--evo-modal-height)) / 2);
35
- width: var(--evo-modal-width);
36
- height: var(--evo-modal-height);
37
- display: none;
38
- margin: 0;
39
- padding: 0;
40
- opacity: 0;
41
- color: #000000;
42
- background-color: #ffffff;
43
- z-index: var(--evo-modal-z-index);
44
- box-sizing: border-box;
45
- animation-duration: var(--evo-modal-animation-duration);
46
- animation-iteration-count: 1;
47
- animation-timing-function: linear;
48
- animation-fill-mode: forwards;
49
-
50
- .evo-modal-close {
51
- /* the button click area is larger than the visible button */
52
- position: absolute;
53
- right: 0px;
54
- top: 0px;
55
- width: 40px;
56
- height: 40px;
57
- background-color: transparent;
58
- border: none;
59
- cursor: pointer;
60
- z-index: var(--evo-modal-z-index);
61
- box-sizing: border-box;
62
-
63
- &.evo-modal-theme-default {
64
- .evo-modal-x {
65
- position: absolute;
66
- right: 8px;
67
- top: 8px;
68
- display: block;
69
- width: 24px;
70
- height: 24px;
71
- background-color: #990000;
72
- border: none;
73
- border-radius: 50%;
74
- text-align: left;
75
- text-indent: -9999px;
76
- transform: rotate(45deg);
77
-
78
- &::before,
79
- &::after {
80
- content: "";
81
- position: absolute;
82
- background-color: #ffffff;
83
- }
84
- &::before {
85
- left: 5px;
86
- top: 11px;
87
- width: 14px;
88
- height: 2px;
89
- }
90
- &::after {
91
- left: 11px;
92
- top: 5px;
93
- width: 2px;
94
- height: 14px;
95
- }
96
- }
97
- }
98
- }
99
-
100
- .evo-modal-wrapper {
101
- position: relative;
102
- width: 100%;
103
- height: 100%;
104
- padding: 1rem;
105
- overflow: hidden;
106
- box-sizing: border-box;
107
-
108
- h1,h2,h3 {
109
- &:first-child {
110
- margin-top: 0;
111
- }
112
- }
113
- }
114
- }
115
-
116
- .evo-modal-visible {
117
- display: block;
118
- }
119
-
120
- .evo-modal-hide-none {
121
- display: none;
122
- opacity: 0;
123
- }
124
- .evo-modal-hide-fade {
125
- /* display: block; */
126
- opacity: 0;
127
- animation-name: evo_modal_hide;
128
- }
129
- .evo-modal-show-none {
130
- display: block;
131
- opacity: 1;
132
- }
133
- .evo-modal-show-fade {
134
- /* display: block; */
135
- opacity: 1;
136
- animation-name: evo_modal_show;
137
- }
138
-
139
- @keyframes evo_modal_show {
140
- 0% {
141
- opacity: 0;
142
- }
143
- 100% {
144
- opacity: 1;
145
- }
146
- }
147
- @keyframes evo_modal_hide {
148
- 0% {
149
- opacity: 1;
150
- }
151
- 100% {
152
- opacity: 0;
153
- }
154
- }
155
- }
@@ -1,219 +0,0 @@
1
-
2
- const TAG_NAME = 'evo-modal';
3
- const CSS_VISIBLE = 'evo-modal-visible';
4
- const CSS_PREFIX_SHOW = 'evo-modal-show';
5
- const CSS_PREFIX_HIDE = 'evo-modal-hide';
6
- const CSS_OVERLAY = 'evo-modal-overlay';
7
-
8
- export type ModalAnimation = 'none' | 'fade';
9
-
10
- export interface ModalEventDetail {
11
- modal: EvoModalElement;
12
- replacedBy?: EvoModalElement;
13
- }
14
- export type ModalEventCallback = (e: CustomEvent<ModalEventDetail>) => void;
15
-
16
- declare global {
17
- interface ElementEventMap {
18
- 'evomodalvisible': CustomEvent<ModalEventDetail>,
19
- 'evomodalhidden': CustomEvent<ModalEventDetail>
20
- }
21
- }
22
- type ModalEventType = 'evomodalvisible' | 'evomodalhidden';
23
-
24
- export class EvoModalElement extends HTMLElement {
25
- #animation: ModalAnimation = 'fade';
26
-
27
- constructor() {
28
- super();
29
- }
30
-
31
- connectedCallback() {
32
- this.querySelectorAll<HTMLElement>('.evo-modal-action-hide').forEach((trigger) => {
33
- trigger.addEventListener('click', () => {
34
- this.hideModal();
35
- }, { passive: true });
36
- })
37
- }
38
-
39
- showModal({ animation = 'fade' }: { animation?: ModalAnimation } = {}): Promise<void> {
40
- return new Promise<void>((resolve) => {
41
- if (!this.classList.contains(CSS_VISIBLE)) {
42
- [...document.querySelectorAll<EvoModalElement>(`${TAG_NAME}.${CSS_VISIBLE}`)]
43
- .forEach((modal) => {
44
- modal.#hideModal({ overlay: false, replacedBy: this });
45
- });
46
- this.#animation = animation;
47
- this.classList.add(CSS_VISIBLE, `${CSS_PREFIX_SHOW}-${animation}`);
48
- showOverlay(this.#animation);
49
-
50
- setTimeout(() => {
51
- this.dispatchEvent(createModalEvent('evomodalvisible', this));
52
- resolve();
53
- }, animation !== 'none' ? getAnimationDuration(this) : 0)
54
- } else {
55
- resolve();
56
- }
57
- });
58
- }
59
-
60
- hideModal({ animation }: { animation?: ModalAnimation } = {}): Promise<void> {
61
- return this.#hideModal({ animation });
62
- }
63
-
64
- #hideModal({ animation, overlay = true, replacedBy }: { animation?: ModalAnimation, overlay?: boolean, replacedBy?: EvoModalElement } = {}): Promise<void> {
65
- return new Promise<void>((resolve) => {
66
- if (this.classList.contains(CSS_VISIBLE)) {
67
- if (!animation) {
68
- animation = this.#animation;
69
- }
70
-
71
- const duration = getAnimationDuration(this);
72
-
73
- this.classList.add(`${CSS_PREFIX_HIDE}-${this.#animation}`);
74
- this.classList.remove(`${CSS_PREFIX_SHOW}-${this.#animation}`);
75
- if (overlay) {
76
- hideOverlay({ modal: this, animation: this.#animation, duration });
77
- }
78
-
79
- setTimeout(() => {
80
- this.classList.remove('evo-modal-visible', `${CSS_PREFIX_HIDE}-${this.#animation}`);
81
- this.dispatchEvent(createModalEvent('evomodalhidden', this, { replacedBy }));
82
- resolve();
83
- }, animation !== 'none' ? duration : 0);
84
- } else {
85
- resolve();
86
- }
87
- });
88
- }
89
- }
90
- if (!customElements.get(TAG_NAME)) {
91
- customElements.define(TAG_NAME, EvoModalElement);
92
- }
93
-
94
- function createModalEvent(type: ModalEventType, modal: EvoModalElement, { replacedBy }: { replacedBy?: EvoModalElement } = {}) {
95
- return new CustomEvent(type, {
96
- detail: { modal, replacedBy },
97
- bubbles: true,
98
- composed: true
99
- });
100
- }
101
-
102
- interface ShowModalOpts {
103
- animation?: ModalAnimation;
104
- onShow?: ModalEventCallback;
105
- onHide?: ModalEventCallback;
106
- }
107
-
108
- export async function showModal(selector: string | HTMLElement, { animation, onShow, onHide }: ShowModalOpts = {}): Promise<EvoModalElement | undefined> {
109
- if (typeof selector == 'string' && selector !== TAG_NAME && !/[#\.]/.test(selector)) {
110
- selector = `#${selector}`; // assume this is an id
111
- }
112
- const modal = typeof selector == 'string' ? document.querySelector<EvoModalElement>(selector) : selector;
113
- if (modal && modal instanceof EvoModalElement) {
114
- if (typeof onShow == 'function') {
115
- modal.addEventListener('evomodalvisible', onShow, { once: true });
116
- }
117
- if (typeof onHide == 'function') {
118
- modal.addEventListener('evomodalhidden', onHide, { once: true });
119
- }
120
- await modal.showModal({ animation });
121
- return modal;
122
- } else {
123
- return undefined;
124
- }
125
- }
126
-
127
- export async function hideModal(selector: string | HTMLElement, animation?: ModalAnimation) {
128
- const modal = typeof selector == 'string' ? document.querySelector<EvoModalElement>(selector) : selector;
129
- if (modal && modal instanceof EvoModalElement) {
130
- await modal.hideModal({ animation });
131
- }
132
- }
133
-
134
- export async function hideModals(animation?: ModalAnimation) {
135
- const modals = [...document.querySelectorAll<EvoModalElement>(`${TAG_NAME}.${CSS_VISIBLE}`)];
136
- await Promise.all(modals.map((m) => { return m.hideModal({ animation })}));
137
- }
138
-
139
- export function showOverlay(animation: ModalAnimation = 'fade') {
140
- const overlay = getOverlay();
141
- if (overlay && !overlay.classList.contains(CSS_VISIBLE)) {
142
- overlay.classList.add(CSS_VISIBLE);
143
- requestAnimationFrame(() => {
144
- overlay.classList.add(`${CSS_PREFIX_SHOW}-${animation}`);
145
- });
146
- }
147
- }
148
- export function hideOverlay({ modal, animation = 'fade', duration }: { modal?: EvoModalElement, animation?: ModalAnimation, duration?: number } = {}) {
149
- const overlay = getOverlay();
150
- if (overlay && overlay.classList.contains(CSS_VISIBLE)) {
151
- const cssShow = [...overlay.classList]
152
- .filter((c) => {
153
- return c.startsWith(CSS_PREFIX_SHOW);
154
- });
155
- const cssHide = [...overlay.classList]
156
- .filter((c) => {
157
- return c.startsWith(CSS_PREFIX_HIDE);
158
- });
159
-
160
- if (cssShow.length !== 0 && cssHide.length === 0) {
161
- cssHide.push(`${CSS_PREFIX_HIDE}-${animation}`)
162
- overlay.classList.add(cssHide[0]);
163
- overlay.classList.remove(cssShow[0]);
164
- setTimeout(() => {
165
- overlay.classList.remove(CSS_VISIBLE, cssHide[0]);
166
- }, duration ?? getAnimationDuration(modal));
167
- }
168
-
169
- }
170
- }
171
-
172
- /**
173
- * Call this function when dynamically adding a trigger to the DOM
174
- */
175
- export function bindTriggers(container = document) {
176
- container.querySelectorAll<HTMLElement>('[data-evo-modal-show]').forEach((trigger) => {
177
- if (!trigger.hasAttribute('data-evo-modal-bound')) {
178
- trigger.setAttribute('data-evo-modal-bound','true');
179
- trigger.addEventListener('click', async (e) => {
180
- e.preventDefault();
181
- const target = (e.currentTarget ?? e.target) as HTMLElement;
182
- const animation = (target.getAttribute('data-evo-modal-animation') ?? undefined) as ModalAnimation | undefined;
183
- await showModal(target.getAttribute('data-evo-modal-show') as string, { animation });
184
- });
185
- }
186
- });
187
- }
188
-
189
- function getOverlay() {
190
- return document.querySelector<HTMLElement>(`.${CSS_OVERLAY}`);
191
- }
192
-
193
- function getAnimationDuration(element: HTMLElement = document.body) {
194
- let duration = 300;
195
- const cssDuration = getComputedStyle(element).getPropertyValue('--evo-modal-animation-duration').trim();
196
- if (cssDuration) {
197
- // Match ms or s suffixes
198
- const match = cssDuration.match(/^(\d+(?:\.\d+)?)(m?s)$/);
199
- if (match) {
200
- const value = parseFloat(match[1]);
201
- const unit = match[2];
202
- duration = unit === 'ms' ? value : value * 1000;
203
- }
204
- }
205
- return duration;
206
- }
207
-
208
- document.addEventListener('DOMContentLoaded', (e) => {
209
- bindTriggers();
210
-
211
- if (!getOverlay()) {
212
- const overlay = document.createElement('div');
213
- overlay.classList.add(CSS_OVERLAY);
214
- overlay.addEventListener('click', () => {
215
- hideModals();
216
- }, { passive: true });
217
- document.body.append(overlay);
218
- }
219
- }, { passive: true });
@@ -1,14 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
-
4
- interface Props extends HTMLAttributes<'div'> {
5
- class?: string;
6
- }
7
-
8
- const {
9
- class: cssClass,
10
- ...rest
11
- } = Astro.props;
12
-
13
- ---
14
- <div class:list={['evo-modal-overlay', cssClass]} {...rest}><slot /></div>
@@ -1,29 +0,0 @@
1
- ---
2
- import type { HTMLAttributes } from "astro/types";
3
- import type { ModalAnimation } from './Modal';
4
-
5
- interface Props extends HTMLAttributes<'button'> {
6
- modal: string;
7
- animation?: ModalAnimation;
8
- }
9
-
10
- const {
11
- modal,
12
- animation,
13
- ...rest
14
- } = Astro.props;
15
-
16
- interface ButtonAttrs extends HTMLAttributes<'button'> {
17
- 'data-evo-modal-show': string;
18
- 'data-evo-modal-animation'?: ModalAnimation
19
- };
20
-
21
- const attrs: ButtonAttrs = {...rest, 'data-evo-modal-show': modal};
22
- if (animation) {
23
- attrs['data-evo-modal-animation'] = animation;
24
- }
25
-
26
- const cssClass = attrs['class'];
27
- delete attrs['class'];
28
- ---
29
- <button class:list={['evo-modal-trigger', cssClass]} {...attrs}><slot /></button>
@@ -1 +0,0 @@
1
- export * from './Modal';