@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
@@ -1,206 +1,223 @@
1
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
+
2
8
  export type ModalAnimation = 'none' | 'fade';
3
- export type ModalEventCallback = (modal: HTMLElement | HTMLElement[]) => void;
4
- interface ModalEventCallbackItem {
5
- once?: boolean;
6
- callback: ModalEventCallback;
7
- }
8
- interface ModalEventCallbackArgs {
9
- once?: boolean
9
+
10
+ export interface ModalEventDetail {
11
+ modal: EvoModalElement;
12
+ replacedBy?: EvoModalElement;
10
13
  }
14
+ export type ModalEventCallback = (e: CustomEvent<ModalEventDetail>) => void;
11
15
 
12
- type ModalEventType = 'show' | 'hide' | 'overlay';
13
- type ModalEventTypeCallbacks = Record<ModalEventType, Set<ModalEventCallbackItem>>;
14
- const callbacks = new Map<HTMLElement, ModalEventTypeCallbacks>();
16
+ declare global {
17
+ interface ElementEventMap {
18
+ 'evomodal-visible': CustomEvent<ModalEventDetail>,
19
+ 'evomodal-hidden': CustomEvent<ModalEventDetail>
20
+ }
21
+ }
22
+ type ModalEventType = 'evomodal-visible' | 'evomodal-hidden';
15
23
 
16
- interface ModalOptions {
17
- animation?: ModalAnimation;
24
+ export interface IEvoModalElement {
25
+ showModal(opts?: { animation?: ModalAnimation }): Promise<void>;
26
+ hideModal(opts?: { animation?: ModalAnimation }): Promise<void>;
18
27
  }
19
- interface ModalShowOptions extends ModalOptions {
20
- on?: {
21
- show?: ModalEventCallback,
22
- hide?: ModalEventCallback
28
+ export class EvoModalElement extends HTMLElement implements IEvoModalElement {
29
+ #animation: ModalAnimation = 'fade';
30
+
31
+ constructor() {
32
+ super();
23
33
  }
24
- }
25
- export function show(selector: string | HTMLElement, { animation = 'fade', on }: ModalShowOptions = {}) {
26
- return new Promise<void>(async (resolve) => {
27
- let modal = typeof selector == 'string' ? document.querySelector<HTMLElement>(/^[\.#]/.test(selector) ? selector : `#${selector}`) : selector;
28
- if (modal) {
29
- if (on?.hide) {
30
- onEvent('hide', modal, { once: true, callback: on.hide });
34
+
35
+ connectedCallback() {
36
+ this.querySelectorAll<HTMLElement>('.evo-modal-action-hide').forEach((trigger) => {
37
+ trigger.addEventListener('click', () => {
38
+ this.hideModal();
39
+ }, { passive: true });
40
+ })
41
+ }
42
+
43
+ showModal({ animation = 'fade' }: { animation?: ModalAnimation } = {}): Promise<void> {
44
+ return new Promise<void>((resolve) => {
45
+ if (!this.classList.contains(CSS_VISIBLE)) {
46
+ [...document.querySelectorAll<EvoModalElement>(`${TAG_NAME}.${CSS_VISIBLE}`)]
47
+ .forEach((modal) => {
48
+ modal.#hideModal({ overlay: false, replacedBy: this });
49
+ });
50
+ this.#animation = animation;
51
+ this.classList.add(CSS_VISIBLE, `${CSS_PREFIX_SHOW}-${animation}`);
52
+ showOverlay(this.#animation);
53
+
54
+ setTimeout(() => {
55
+ this.dispatchEvent(createModalEvent('evomodal-visible', this));
56
+ resolve();
57
+ }, animation !== 'none' ? getAnimationDuration(this) : 0)
58
+ } else {
59
+ resolve();
31
60
  }
32
- await hide(null, { animation, hideOverlay: false });
33
- __showOverlay(animation);
61
+ });
62
+ }
34
63
 
35
- modal.classList.add('evo-modal-visible', `evo-modal-show-${animation}`);
36
- setTimeout(() => {
37
- triggerEventCallbacks(modal, 'show');
38
- if (on?.show) {
39
- try {
40
- on.show(modal);
41
- } catch (err) {
42
- console.log(err);
43
- }
64
+ hideModal({ animation }: { animation?: ModalAnimation } = {}): Promise<void> {
65
+ return this.#hideModal({ animation });
66
+ }
67
+
68
+ #hideModal({ animation, overlay = true, replacedBy }: { animation?: ModalAnimation, overlay?: boolean, replacedBy?: EvoModalElement } = {}): Promise<void> {
69
+ return new Promise<void>((resolve) => {
70
+ if (this.classList.contains(CSS_VISIBLE)) {
71
+ if (!animation) {
72
+ animation = this.#animation;
73
+ }
74
+
75
+ const duration = getAnimationDuration(this);
76
+
77
+ this.classList.add(`${CSS_PREFIX_HIDE}-${this.#animation}`);
78
+ this.classList.remove(`${CSS_PREFIX_SHOW}-${this.#animation}`);
79
+ if (overlay) {
80
+ hideOverlay({ modal: this, animation: this.#animation, duration });
44
81
  }
82
+
83
+ setTimeout(() => {
84
+ this.classList.remove('evo-modal-visible', `${CSS_PREFIX_HIDE}-${this.#animation}`);
85
+ this.dispatchEvent(createModalEvent('evomodal-hidden', this, { replacedBy }));
86
+ resolve();
87
+ }, animation !== 'none' ? duration : 0);
88
+ } else {
45
89
  resolve();
46
- }, animation !== 'none' ? getAnimationDuration(modal) : 0);
47
- }
48
- });
49
- }
50
- function __showOverlay(animation: ModalAnimation) {
51
- if (!overlay.classList.contains('evo-modal-visible')) {
52
- overlay.setAttribute('data-evo-modal-animation', animation);
53
- overlay.classList.add('evo-modal-visible', `evo-modal-show-${animation}`);
90
+ }
91
+ });
54
92
  }
55
93
  }
56
- export function onShow(selector: string | HTMLElement, callback: ModalEventCallback, { once }: ModalEventCallbackArgs = {}) {
57
- onEvent('show', selector, { once, callback });
94
+ if (!customElements.get(TAG_NAME)) {
95
+ customElements.define(TAG_NAME, EvoModalElement);
58
96
  }
59
97
 
60
- interface HideModalOptions extends ModalOptions {
61
- hideOverlay?: boolean;
62
- on?: {
63
- hide?: ModalEventCallback
64
- }
65
- }
66
- export function hide(selector?: string | HTMLElement | (string | HTMLElement)[] | null, { animation, hideOverlay = true, on }: HideModalOptions = {}) {
67
- return new Promise<void>(async (resolve) => {
68
- const modals: HTMLElement[] = (selector ? Array.isArray(selector) ? selector : [selector] : [...document.querySelectorAll<HTMLElement>('.evo-modal.evo-modal-visible')])
69
- .map((m) => {
70
- return typeof m == 'string' ? document.querySelector<HTMLElement>(/^[\.#]/.test(m) ? m : `#${m}`) : m;
71
- })
72
- .filter(m => m !== undefined && m !== null);
73
-
74
- const hides = [];
75
- if (!animation) {
76
- if (modals.length) {
77
- animation = ([...modals[0].classList.values()].find((c) => { return c.startsWith('evo-modal-show'); }) ?? 'evo-modal-show-fade').substring(15) as ModalAnimation;
78
- } else {
79
- animation = 'fade';
80
- }
81
- }
82
- for (let modal of modals) {
83
- hides.push(__hide(modal, animation));
84
- }
85
- if (hideOverlay) {
86
- hides.push(__hide(overlay, animation));
87
- }
88
- await Promise.all(hides);
89
- if (on?.hide) {
90
- try {
91
- on.hide(modals);
92
- } catch (err) {
93
- console.log(err);
94
- }
95
- }
96
- resolve();
98
+ function createModalEvent(type: ModalEventType, modal: EvoModalElement, { replacedBy }: { replacedBy?: EvoModalElement } = {}) {
99
+ return new CustomEvent(type, {
100
+ detail: { modal, replacedBy },
101
+ bubbles: true,
102
+ composed: true
97
103
  });
98
104
  }
99
- function __hide(modal: HTMLElement, animation: ModalAnimation) {
100
- return new Promise<void>((resolve) => {
101
- const showClass = [...modal.classList.values()].find((c) => { return c.startsWith('evo-modal-show'); }) ?? 'evo-modal-show-fade';
102
- modal.classList.add(`evo-modal-hide-${animation}`);
103
- modal.classList.remove(showClass);
104
- setTimeout(() => {
105
- modal.classList.remove('evo-modal-visible', `evo-modal-hide-${animation}`);
106
- triggerEventCallbacks(modal, 'hide');
107
- resolve();
108
- }, animation !== 'none' ? getAnimationDuration(modal) : 0);
109
- });
105
+
106
+ interface ShowModalOpts {
107
+ animation?: ModalAnimation;
108
+ onShow?: ModalEventCallback;
109
+ onHide?: ModalEventCallback;
110
110
  }
111
- export function onHide(selector: string | HTMLElement, callback: ModalEventCallback, { once }: ModalEventCallbackArgs = {}) {
112
- onEvent('hide', selector, { once, callback });
111
+
112
+ export async function showModal(selector: string | HTMLElement, { animation, onShow, onHide }: ShowModalOpts = {}): Promise<EvoModalElement | undefined> {
113
+ if (typeof selector == 'string' && selector !== TAG_NAME && !/[#\.]/.test(selector)) {
114
+ selector = `#${selector}`; // assume this is an id
115
+ }
116
+ const modal = typeof selector == 'string' ? document.querySelector<EvoModalElement>(selector) : selector;
117
+ if (modal && modal instanceof EvoModalElement) {
118
+ if (typeof onShow == 'function') {
119
+ modal.addEventListener('evomodal-visible', onShow, { once: true });
120
+ }
121
+ if (typeof onHide == 'function') {
122
+ modal.addEventListener('evomodal-hidden', onHide, { once: true });
123
+ }
124
+ await modal.showModal({ animation });
125
+ return modal;
126
+ } else {
127
+ return undefined;
128
+ }
113
129
  }
114
130
 
115
- /**
116
- * Moves the overlay element by appending it to an element
117
- * @param selector
118
- */
119
- export function appendOverlay(selector: string | HTMLElement) {
120
- const container = typeof selector == 'string' ? document.querySelector(selector) : selector;
121
- if (container) {
122
- container.appendChild(overlay);
131
+ export async function hideModal(selector: string | HTMLElement, animation?: ModalAnimation) {
132
+ const modal = typeof selector == 'string' ? document.querySelector<EvoModalElement>(selector) : selector;
133
+ if (modal && modal instanceof EvoModalElement) {
134
+ await modal.hideModal({ animation });
123
135
  }
124
136
  }
125
137
 
126
- export function onOverlayClick(callback: ModalEventCallback, { once }: ModalEventCallbackArgs = {}) {
127
- onEvent('overlay', overlay, { once, callback });
138
+ export async function hideModals(animation?: ModalAnimation) {
139
+ const modals = [...document.querySelectorAll<EvoModalElement>(`${TAG_NAME}.${CSS_VISIBLE}`)];
140
+ await Promise.all(modals.map((m) => { return m.hideModal({ animation })}));
128
141
  }
129
142
 
130
- function onEvent(type: ModalEventType, selector: string | HTMLElement, callbackItem: ModalEventCallbackItem) {
131
- let modal = typeof selector == 'string' ? document.querySelector<HTMLElement>(/^[\.#]/.test(selector) ? selector : `#${selector}`) : selector;
132
- if (modal) {
133
- const modalCallbacks = callbacks.get(modal) ?? {} as ModalEventTypeCallbacks;
134
- if (!modalCallbacks[type]) {
135
- modalCallbacks[type] = new Set();
136
- }
137
- modalCallbacks[type].add(callbackItem);
138
- callbacks.set(modal, modalCallbacks);
143
+ export function showOverlay(animation: ModalAnimation = 'fade') {
144
+ const overlay = getOverlay();
145
+ if (overlay && !overlay.classList.contains(CSS_VISIBLE)) {
146
+ overlay.classList.add(CSS_VISIBLE);
147
+ requestAnimationFrame(() => {
148
+ overlay.classList.add(`${CSS_PREFIX_SHOW}-${animation}`);
149
+ });
139
150
  }
140
151
  }
152
+ export function hideOverlay({ modal, animation = 'fade', duration }: { modal?: EvoModalElement, animation?: ModalAnimation, duration?: number } = {}) {
153
+ const overlay = getOverlay();
154
+ if (overlay && overlay.classList.contains(CSS_VISIBLE)) {
155
+ const cssShow = [...overlay.classList]
156
+ .filter((c) => {
157
+ return c.startsWith(CSS_PREFIX_SHOW);
158
+ });
159
+ const cssHide = [...overlay.classList]
160
+ .filter((c) => {
161
+ return c.startsWith(CSS_PREFIX_HIDE);
162
+ });
141
163
 
142
- function triggerEventCallbacks(element: HTMLElement, eventType: ModalEventType) {
143
- if (element) {
144
- const eventCallbacks = callbacks.get(element);
145
- if (eventCallbacks && eventCallbacks[eventType]) {
146
- const items = [...eventCallbacks[eventType]];
147
- const keep: ModalEventCallbackItem[] = [];
148
- for (const item of items) {
149
- try {
150
- item.callback(element);
151
- } catch (err) {
152
- console.log(err);
153
- } finally {
154
- if (!item.once) {
155
- keep.push(item);
156
- }
157
- }
158
- }
159
- callbacks.set(element, {...eventCallbacks, [eventType]: new Set(keep)});
164
+ if (cssShow.length !== 0 && cssHide.length === 0) {
165
+ cssHide.push(`${CSS_PREFIX_HIDE}-${animation}`)
166
+ overlay.classList.add(cssHide[0]);
167
+ overlay.classList.remove(cssShow[0]);
168
+ setTimeout(() => {
169
+ overlay.classList.remove(CSS_VISIBLE, cssHide[0]);
170
+ }, duration ?? getAnimationDuration(modal));
160
171
  }
172
+
161
173
  }
162
174
  }
163
175
 
164
- const overlay: HTMLElement = document.querySelector<HTMLElement>('.evo-modal-overlay') ?? (() => {
165
- // create the overlay
166
- const div = document.createElement('div');
167
- div.classList.add('evo-modal-overlay');
168
- document.body.append(div);
169
- return div;
170
- })();
171
- overlay.addEventListener('click', () => {
172
- hide();
173
- triggerEventCallbacks(overlay, 'overlay');
174
- });
176
+ /**
177
+ * Call this function when dynamically adding a trigger to the DOM
178
+ */
179
+ export function bindTriggers(container = document) {
180
+ container.querySelectorAll<HTMLElement>('[data-evo-modal-show]').forEach((trigger) => {
181
+ if (!trigger.hasAttribute('data-evo-modal-bound')) {
182
+ trigger.setAttribute('data-evo-modal-bound','true');
183
+ trigger.addEventListener('click', async (e) => {
184
+ e.preventDefault();
185
+ const target = (e.currentTarget ?? e.target) as HTMLElement;
186
+ const animation = (target.getAttribute('data-evo-modal-animation') ?? undefined) as ModalAnimation | undefined;
187
+ await showModal(target.getAttribute('data-evo-modal-show') as string, { animation });
188
+ });
189
+ }
190
+ });
191
+ }
192
+
193
+ function getOverlay() {
194
+ return document.querySelector<HTMLElement>(`.${CSS_OVERLAY}`);
195
+ }
175
196
 
176
197
  function getAnimationDuration(element: HTMLElement = document.body) {
177
- let duration = 0;
178
- const cssDuration = getComputedStyle(element).getPropertyValue('--evo-modal-animation-duration').trim();
179
- if (cssDuration) {
180
- // Match ms or s suffixes
181
- const match = cssDuration.match(/^(\d+(?:\.\d+)?)(m?s)$/);
182
- if (match) {
183
- const value = parseFloat(match[1]);
184
- const unit = match[2];
185
- duration = unit === 'ms' ? value : value * 1000;
198
+ let duration = 300;
199
+ const cssDuration = getComputedStyle(element).getPropertyValue('--evo-modal-animation-duration').trim();
200
+ if (cssDuration) {
201
+ // Match ms or s suffixes
202
+ const match = cssDuration.match(/^(\d+(?:\.\d+)?)(m?s)$/);
203
+ if (match) {
204
+ const value = parseFloat(match[1]);
205
+ const unit = match[2];
206
+ duration = unit === 'ms' ? value : value * 1000;
207
+ }
186
208
  }
209
+ return duration;
187
210
  }
188
- return duration;
189
- };
190
211
 
191
- document.querySelectorAll<HTMLElement>('.evo-modal').forEach((modal) => {
192
- modal.querySelectorAll<HTMLElement>('.evo-modal-action-hide').forEach((btn) => {
193
- btn.addEventListener('click', async () => {
194
- hide(modal);
195
- });
196
- });
197
- });
198
-
199
- document.querySelectorAll<HTMLElement>('[data-evo-modal-show]').forEach((trigger) => {
200
- trigger.addEventListener('click', async (e) => {
201
- e.preventDefault();
202
- const target = (e.currentTarget ?? e.target) as HTMLElement;
203
- const animation = (target.getAttribute('data-evo-modal-animation') ?? undefined) as ModalAnimation | undefined;
204
- await show(target.getAttribute('data-evo-modal-show') as string, { animation });
205
- });
206
- });
212
+ document.addEventListener('DOMContentLoaded', (e) => {
213
+ bindTriggers();
214
+
215
+ if (!getOverlay()) {
216
+ const overlay = document.createElement('div');
217
+ overlay.classList.add(CSS_OVERLAY);
218
+ overlay.addEventListener('click', () => {
219
+ hideModals();
220
+ }, { passive: true });
221
+ document.body.append(overlay);
222
+ }
223
+ }, { passive: true });
@@ -40,7 +40,7 @@ if (height) {
40
40
  attrs.style = `${attrs.style ? `${attrs.style}${attrs.style.endsWith(';') ? '' : ';'}` : ''}--evo-pdf-viewer-height:${typeof height == 'number' ? `${height}px` : height};`;
41
41
  }
42
42
  ---
43
- <div
43
+ <evo-pdf-viewer
44
44
  id={id}
45
45
  class:list={['evo-pdf-viewer', cssClass, theme ? `evo-pdf-viewer-theme-${theme}` : null]}
46
46
  data-pdf={pdf}
@@ -97,7 +97,7 @@ if (height) {
97
97
  {toolbar?.bookmarks && Object.keys(toolbar.bookmarks.items).length > 0 &&
98
98
  <div class="evo-pdf-viewer-toolbar-bookmarks">
99
99
  <select>
100
- <option value="" disabled selected hidden>{toolbar.bookmarks.placeholder ?? 'Jump To'}</option>
100
+ <option value="" disabled selected hidden>{toolbar.bookmarks.placeholder ?? ''}</option>
101
101
  {Object.entries(toolbar.bookmarks.items).map((b) => (
102
102
  <option value={b[1]}>{b[0]}</option>
103
103
  ))}
@@ -118,4 +118,7 @@ if (height) {
118
118
  </div> -->
119
119
  </ScrollContainer>
120
120
  </div>
121
- </div>
121
+ </evo-pdf-viewer>
122
+ <script>
123
+ import './PdfViewer';
124
+ </script>
@@ -1,10 +1,11 @@
1
- .evo-pdf-viewer {
2
- --evo-pdf-viewer-height: 100%;
1
+ evo-pdf-viewer {
2
+ --evo-pdf-viewer-height: 100vh;
3
3
  --evo-pdf-viewer-toolbar-height: 44px;
4
4
  --evo-pdf-viewer-toolbar-align: center;
5
5
  --evo-pdf-viewer-scale: 1;
6
6
 
7
7
  position: relative;
8
+ display: block;
8
9
  height: var(--evo-pdf-viewer-height);
9
10
  background-color: #f0f0f0;
10
11
  box-sizing: border-box;
@@ -139,8 +140,9 @@
139
140
  padding: 0 9px 9px var(--evo-scroll-container-content-padding-right);
140
141
  box-sizing: border-box;
141
142
 
142
- .evo-scroll-container {
143
+ evo-scroll-container {
143
144
  --evo-scroll-container-track-color: #cccccc;
145
+ height: calc(var(--evo-pdf-viewer-height) - var(--evo-pdf-viewer-toolbar-height));
144
146
  .evo-scroll-content {
145
147
  overflow-x: hidden;
146
148
  .evo-pdf-viewer-page-wrapper {