well-petal 0.0.24 → 0.0.25
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/dist/petal.js +228 -0
- package/package.json +5 -2
- package/.gitattributes +0 -2
- package/.prettierrc +0 -5
- package/demo/index.html +0 -124
- package/demo/styles.css +0 -244
- package/src/animation.ts +0 -108
- package/src/banner.ts +0 -44
- package/src/lib/animations.ts +0 -76
- package/src/lib/attributes.ts +0 -48
- package/src/lib/breakpoints.ts +0 -4
- package/src/lib/console.ts +0 -51
- package/src/lib/elements.ts +0 -0
- package/src/lib/helpers.ts +0 -5
- package/src/lib/memory.ts +0 -54
- package/src/petal.css +0 -11
- package/src/petal.ts +0 -8
- package/src/popup.ts +0 -141
- package/src/types/env.d.ts +0 -1
- package/src/video.ts +0 -6
- package/tsconfig.json +0 -24
- package/webpack.config.js +0 -58
package/src/lib/console.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// Custom Error classes for Petal
|
|
2
|
-
export class PetalError extends Error {
|
|
3
|
-
constructor(
|
|
4
|
-
message: string,
|
|
5
|
-
public readonly element?: Element,
|
|
6
|
-
public readonly petalName?: string
|
|
7
|
-
) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = "PetalError";
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class MissingNameError extends PetalError {
|
|
14
|
-
constructor(trigger: Element) {
|
|
15
|
-
super('Trigger is missing the "petal" attribute', trigger);
|
|
16
|
-
this.name = "MissingNameError";
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export class MissingPopupError extends PetalError {
|
|
21
|
-
constructor(popupName: string, trigger: Element) {
|
|
22
|
-
super(`Popup with name "${popupName}" not found`, trigger, popupName);
|
|
23
|
-
this.name = "MissingPopupError";
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class MissingTriggerError extends PetalError {
|
|
28
|
-
constructor(popupName: string, trigger: Element) {
|
|
29
|
-
super(`Trigger error for "${popupName}"`, trigger, popupName);
|
|
30
|
-
this.name = "MissingTriggerError";
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class MissingMaskError extends PetalError {
|
|
35
|
-
constructor(popupName: string, trigger: Element) {
|
|
36
|
-
super(`Mask not found for "${popupName}"`, trigger, popupName);
|
|
37
|
-
this.name = "MissingMaskError";
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export class MissingSlotError extends PetalError {
|
|
42
|
-
constructor(popupName: string, trigger: Element) {
|
|
43
|
-
super(`Slot not found for "${popupName}"`, trigger, popupName);
|
|
44
|
-
this.name = "MissingSlotError";
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Helper function to log errors (for backward compatibility or simple logging)
|
|
49
|
-
export function logPetalError(error: PetalError): void {
|
|
50
|
-
console.error(`[${error.name}]:`, error.message, error.element);
|
|
51
|
-
}
|
package/src/lib/elements.ts
DELETED
|
File without changes
|
package/src/lib/helpers.ts
DELETED
package/src/lib/memory.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { PetalElements } from "./attributes";
|
|
2
|
-
|
|
3
|
-
// MEMORY
|
|
4
|
-
type MemoryItem = "popup" | "banner";
|
|
5
|
-
|
|
6
|
-
export function storeClosedState(type: MemoryItem, petal: PetalElements) {
|
|
7
|
-
const { name } = petal;
|
|
8
|
-
const now = new Date();
|
|
9
|
-
sessionStorage.setItem(getMemoryKey(type, name), now.getTime().toString());
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Check Closed State in Session Storage
|
|
14
|
-
* @param type The type of element (popup or banner)
|
|
15
|
-
* @param petal The Petal to check
|
|
16
|
-
* @param sessionTTLMinutes The length that the session is valid for (in minutes)
|
|
17
|
-
* @returns True if the element has been closed in this session and the session is still valid, false otherwise
|
|
18
|
-
*/
|
|
19
|
-
export function checkClosedState(type: MemoryItem, petal: PetalElements, sessionTTLMinutes: number): boolean {
|
|
20
|
-
const { name } = petal;
|
|
21
|
-
const timestampStr = sessionStorage.getItem(getMemoryKey(type, name));
|
|
22
|
-
if (!timestampStr) return false;
|
|
23
|
-
|
|
24
|
-
const timestamp = parseInt(timestampStr, 10);
|
|
25
|
-
if (isNaN(timestamp)) {
|
|
26
|
-
sessionStorage.removeItem(getMemoryKey(type, name));
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const now = new Date();
|
|
31
|
-
const itemTime = new Date(timestamp);
|
|
32
|
-
const diffMinutes = (now.getTime() - itemTime.getTime()) / (1000 * 60);
|
|
33
|
-
|
|
34
|
-
if (diffMinutes > sessionTTLMinutes) {
|
|
35
|
-
// Session expired
|
|
36
|
-
sessionStorage.removeItem(getMemoryKey(type, name));
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Legacy function names for backward compatibility
|
|
44
|
-
export function storePopupClosedState(petal: PetalElements) {
|
|
45
|
-
storeClosedState("popup", petal);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function checkPopupClosedState(petal: PetalElements, sessionTTLMinutes: number): boolean {
|
|
49
|
-
return checkClosedState("popup", petal, sessionTTLMinutes);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function getMemoryKey(key: MemoryItem, name: string) {
|
|
53
|
-
return `petal_memory_${key}_${name}`;
|
|
54
|
-
}
|
package/src/petal.css
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/** BANNER **/
|
|
2
|
-
.petal-hide-nav-banner [petal-el="banner"] {
|
|
3
|
-
display: none;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
/** NAV **/
|
|
7
|
-
|
|
8
|
-
/* Disable scrolling when mobile nav is open */
|
|
9
|
-
body:has([petal-el="nav"] .w-nav-button.w--open):not(:has([petal-el="nav-desktop"]:not(.w-condition-invisible))) {
|
|
10
|
-
overflow: hidden;
|
|
11
|
-
}
|
package/src/petal.ts
DELETED
package/src/popup.ts
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { gsap } from "gsap";
|
|
2
|
-
import { getPopupGSAPAnimation } from "./animation";
|
|
3
|
-
import { MissingMaskError, MissingNameError, MissingPopupError, MissingSlotError, PetalError } from "./lib/console";
|
|
4
|
-
import { animateMaskOpen, animateMaskClosed } from "./lib/animations";
|
|
5
|
-
import { PetalElements, ATTR_PETAL_MASK_OPACITY, ATTR_PETAL_OPEN, ATTR_PETAL_CLOSE, ATTR_PETAL_MASK_CLOSE, ATTR_PETAL_ELEMENT, ATTR_PETAL_POPUP, ATTR_PETAL_NAME } from "./lib/attributes";
|
|
6
|
-
import { getAllPetalElementsOfType } from "./lib/helpers";
|
|
7
|
-
import { storePopupClosedState } from "./lib/memory";
|
|
8
|
-
import { pauseVideo } from "./video";
|
|
9
|
-
|
|
10
|
-
export function initializeAllPopups(): void {
|
|
11
|
-
const popups = getAllPetalElementsOfType(ATTR_PETAL_POPUP);
|
|
12
|
-
|
|
13
|
-
console.log(`🌸 Detected ${popups.length} popup(s)`);
|
|
14
|
-
|
|
15
|
-
popups.forEach((popup) => {
|
|
16
|
-
const popupElement = popup as HTMLElement;
|
|
17
|
-
const name = popup.getAttribute(ATTR_PETAL_NAME) || "unknown";
|
|
18
|
-
console.log(` → Popup: "${name}"`);
|
|
19
|
-
|
|
20
|
-
const mask = findPopupElement(popup, "mask") as HTMLElement | null;
|
|
21
|
-
const slot = findPopupElement(popup, "slot") as HTMLElement | null;
|
|
22
|
-
|
|
23
|
-
// Set slot opacity to 0
|
|
24
|
-
if (slot) slot.style.opacity = "0";
|
|
25
|
-
|
|
26
|
-
// Set mask opacity to 0
|
|
27
|
-
if (mask) mask.style.opacity = "0";
|
|
28
|
-
|
|
29
|
-
// Set popup display to none
|
|
30
|
-
popupElement.style.display = "none";
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function openPopup(petal: PetalElements): void {
|
|
35
|
-
const { name, popup, slot, mask } = petal;
|
|
36
|
-
const tl = gsap.timeline();
|
|
37
|
-
|
|
38
|
-
// Set Popup display to flex
|
|
39
|
-
tl.set(popup, { display: "flex" });
|
|
40
|
-
// Animate Mask open
|
|
41
|
-
const maskOpacity = parseFloat(mask?.getAttribute(ATTR_PETAL_MASK_OPACITY) || "0.15");
|
|
42
|
-
tl.fromTo(mask, animateMaskOpen(maskOpacity).from, animateMaskOpen(maskOpacity).to, "<");
|
|
43
|
-
// Animate Slot Open
|
|
44
|
-
const anim = getPopupGSAPAnimation(popup, "open");
|
|
45
|
-
tl.set(slot, { clearProps: "x,y,scale,transform" });
|
|
46
|
-
tl.fromTo(slot, anim.from, anim.to);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function closePopup(petal: PetalElements): void {
|
|
50
|
-
const { name, popup, slot, mask } = petal;
|
|
51
|
-
const tl = gsap.timeline();
|
|
52
|
-
|
|
53
|
-
// VIDEO: Pause any videos inside the popup
|
|
54
|
-
pauseVideo(popup);
|
|
55
|
-
// SESSION: Store popup closed state
|
|
56
|
-
storePopupClosedState(petal);
|
|
57
|
-
// Animate the Slot Closed
|
|
58
|
-
const anim = getPopupGSAPAnimation(popup, "close");
|
|
59
|
-
tl.fromTo(slot, anim.from, anim.to);
|
|
60
|
-
// Animate Mask Closed
|
|
61
|
-
if (mask) tl.to(mask, animateMaskClosed(0).to, "<");
|
|
62
|
-
|
|
63
|
-
// Hide the Popup and clear transforms so they don't persist
|
|
64
|
-
tl.set(popup, { display: "none" });
|
|
65
|
-
tl.set(slot, { clearProps: "x,y,scale,transform" });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function initializePopupTriggers(): void {
|
|
69
|
-
// Initialize Popup Open Triggers
|
|
70
|
-
const openTriggers = getAllPetalElementsOfType(ATTR_PETAL_OPEN);
|
|
71
|
-
console.log(`🌸 Detected ${openTriggers.length} open trigger(s)`);
|
|
72
|
-
forEachPopupTrigger(openTriggers, (petal) => {
|
|
73
|
-
const { trigger } = petal;
|
|
74
|
-
console.log(` → Open trigger for: "${petal.name}"`);
|
|
75
|
-
trigger.addEventListener("click", () => openPopup(petal));
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// Initialize Popup Close Triggers
|
|
79
|
-
const closeTriggers = getAllPetalElementsOfType(ATTR_PETAL_CLOSE);
|
|
80
|
-
console.log(`🌸 Detected ${closeTriggers.length} close trigger(s)`);
|
|
81
|
-
forEachPopupTrigger(closeTriggers, (petal) => {
|
|
82
|
-
const { trigger } = petal;
|
|
83
|
-
console.log(` → Close trigger for: "${petal.name}"`);
|
|
84
|
-
trigger.addEventListener("click", () => closePopup(petal));
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// Initialize Mask Close Triggers (masks with petal-mask-close="true")
|
|
88
|
-
const popups = getAllPetalElementsOfType(ATTR_PETAL_POPUP);
|
|
89
|
-
popups.forEach((popup) => {
|
|
90
|
-
const mask = findPopupElement(popup, "mask") as HTMLElement | null;
|
|
91
|
-
const maskClose = popup.getAttribute(ATTR_PETAL_MASK_CLOSE) === "true";
|
|
92
|
-
if (mask && maskClose) {
|
|
93
|
-
mask.addEventListener("click", () => {
|
|
94
|
-
const slot = findPopupElement(popup, "slot") as HTMLElement | null;
|
|
95
|
-
const name = popup.getAttribute(ATTR_PETAL_NAME) || popup.id;
|
|
96
|
-
if (slot) {
|
|
97
|
-
closePopup({ name, popup: popup as HTMLElement, slot, mask, trigger: mask });
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function findPetal(el: Element): HTMLElement {
|
|
105
|
-
const popupName = el.getAttribute(ATTR_PETAL_NAME);
|
|
106
|
-
if (!popupName) throw new MissingNameError(el);
|
|
107
|
-
|
|
108
|
-
const popup = document.querySelector(`[${ATTR_PETAL_NAME}='${popupName}'][${ATTR_PETAL_ELEMENT}='${ATTR_PETAL_POPUP}']`) as HTMLElement | null;
|
|
109
|
-
if (!popup) throw new MissingPopupError(popupName, el);
|
|
110
|
-
|
|
111
|
-
return popup;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function findPopupElement(popup: Element, attr: string): HTMLElement | null {
|
|
115
|
-
return popup.querySelector(`[${ATTR_PETAL_ELEMENT}='${attr}']`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Helper to iterate over triggers with error handling
|
|
119
|
-
export function forEachPopupTrigger(triggers: NodeListOf<Element>, callback: (petal: PetalElements) => void): void {
|
|
120
|
-
triggers.forEach((trigger) => {
|
|
121
|
-
try {
|
|
122
|
-
const popup = findPetal(trigger);
|
|
123
|
-
const name = trigger.getAttribute(ATTR_PETAL_NAME) || "unknown";
|
|
124
|
-
|
|
125
|
-
const mask = popup.querySelector(`[${ATTR_PETAL_ELEMENT}='mask']`) as HTMLElement;
|
|
126
|
-
if (!mask) throw new MissingMaskError(name, trigger);
|
|
127
|
-
|
|
128
|
-
const slot = popup.querySelector(`[${ATTR_PETAL_ELEMENT}='slot']`) as HTMLElement;
|
|
129
|
-
if (!slot) throw new MissingSlotError(name, trigger);
|
|
130
|
-
|
|
131
|
-
callback({ name, trigger: trigger as HTMLElement, popup, mask, slot });
|
|
132
|
-
} catch (error) {
|
|
133
|
-
if (error instanceof PetalError) {
|
|
134
|
-
// Log and skip invalid triggers
|
|
135
|
-
console.error(`[${error.name}]:`, error.message, error.element);
|
|
136
|
-
} else {
|
|
137
|
-
throw error; // Re-throw unexpected errors
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
}
|
package/src/types/env.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
declare const APP_VERSION: string;
|
package/src/video.ts
DELETED
package/tsconfig.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"strict": true,
|
|
4
|
-
"noImplicitAny": true,
|
|
5
|
-
"strictNullChecks": true,
|
|
6
|
-
"strictFunctionTypes": true,
|
|
7
|
-
"target": "es2016",
|
|
8
|
-
"module": "ESNext",
|
|
9
|
-
"checkJs": true,
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"skipLibCheck": true,
|
|
13
|
-
"outDir": "package/dist",
|
|
14
|
-
"baseUrl": "./src",
|
|
15
|
-
"resolveJsonModule": true,
|
|
16
|
-
"sourceMap": true,
|
|
17
|
-
"types": ["jquery"]
|
|
18
|
-
},
|
|
19
|
-
"files": [
|
|
20
|
-
"node_modules/gsap/types/index.d.ts",
|
|
21
|
-
],
|
|
22
|
-
"include": ["src/**/*", "src/**/*.tsx", "src/types/**/*.d.ts"],
|
|
23
|
-
"exclude": ["node_modules"]
|
|
24
|
-
}
|
package/webpack.config.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// webpack.config.js
|
|
2
|
-
const webpack = require('webpack');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
|
|
5
|
-
module.exports = {
|
|
6
|
-
entry: "./src/petal.ts",
|
|
7
|
-
output: {
|
|
8
|
-
path: path.resolve(__dirname, 'dist'),
|
|
9
|
-
filename: 'petal.js', // Output bundle file
|
|
10
|
-
library: 'petal', // Name of the global variable if your package is used in the browser
|
|
11
|
-
libraryTarget: 'umd', // Universal module definition, for browser and Node.js
|
|
12
|
-
globalObject: 'this', // Ensures compatibility in different environments
|
|
13
|
-
},
|
|
14
|
-
module: {
|
|
15
|
-
rules: [
|
|
16
|
-
{
|
|
17
|
-
test: /\.css$/, // Apply this rule to all `.css` files
|
|
18
|
-
use: [
|
|
19
|
-
'style-loader', // Injects CSS into the DOM
|
|
20
|
-
'css-loader', // Turns CSS into CommonJS
|
|
21
|
-
],
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
test: /\.ts$/,
|
|
25
|
-
use: 'ts-loader',
|
|
26
|
-
exclude: /node_modules/,
|
|
27
|
-
}
|
|
28
|
-
],
|
|
29
|
-
},
|
|
30
|
-
externals: {
|
|
31
|
-
// Any dependencies you don't want to include in your bundle
|
|
32
|
-
'some-other-external': 'commonjs2 some-other-external',
|
|
33
|
-
},
|
|
34
|
-
mode: 'development', // Can be 'development' for debugging
|
|
35
|
-
resolve: {
|
|
36
|
-
extensions: ['.js', '.ts', '.json'], // Add file extensions you use
|
|
37
|
-
},
|
|
38
|
-
plugins: [
|
|
39
|
-
new webpack.DefinePlugin({
|
|
40
|
-
APP_VERSION: JSON.stringify(require('./package.json').version),
|
|
41
|
-
}),
|
|
42
|
-
],
|
|
43
|
-
devServer: {
|
|
44
|
-
static: [
|
|
45
|
-
{
|
|
46
|
-
directory: path.join(__dirname, 'demo'),
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
directory: path.join(__dirname, 'dist'),
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
compress: true,
|
|
53
|
-
port: 8080,
|
|
54
|
-
hot: true,
|
|
55
|
-
open: true,
|
|
56
|
-
watchFiles: ['src/**/*.ts', 'demo/**/*'],
|
|
57
|
-
},
|
|
58
|
-
};
|