well-petal 0.0.23 → 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.
@@ -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
- }
File without changes
@@ -1,5 +0,0 @@
1
- import { ATTR_PETAL_ELEMENT } from "./attributes";
2
-
3
- export function getAllPetalElementsOfType(el: string): NodeListOf<Element> {
4
- return document.querySelectorAll(`[${ATTR_PETAL_ELEMENT}='${el}']`);
5
- }
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
@@ -1,5 +0,0 @@
1
- import { initializeAllPopups } from "./popup";
2
- import { initializeBanner } from "./banner";
3
-
4
- initializeAllPopups();
5
- initializeBanner();
package/src/popup.ts DELETED
@@ -1,132 +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
- popups.forEach((popup) => {
14
- const popupElement = popup as HTMLElement;
15
- const mask = findPopupElement(popup, "mask") as HTMLElement | null;
16
- const slot = findPopupElement(popup, "slot") as HTMLElement | null;
17
-
18
- // Set slot opacity to 0
19
- if (slot) slot.style.opacity = "0";
20
-
21
- // Set mask opacity to 0
22
- if (mask) mask.style.opacity = "0";
23
-
24
- // Set popup display to none
25
- popupElement.style.display = "none";
26
- });
27
- }
28
-
29
- export function openPopup(petal: PetalElements): void {
30
- const { name, popup, slot, mask } = petal;
31
- const tl = gsap.timeline();
32
-
33
- // Set Popup display to flex
34
- tl.set(popup, { display: "flex" });
35
- // Animate Mask open
36
- const maskOpacity = parseFloat(mask?.getAttribute(ATTR_PETAL_MASK_OPACITY) || "0.15");
37
- tl.fromTo(mask, animateMaskOpen(maskOpacity).from, animateMaskOpen(maskOpacity).to, "<");
38
- // Animate Slot Open
39
- const anim = getPopupGSAPAnimation(popup, "open");
40
- tl.set(slot, { clearProps: "x,y,scale,transform" });
41
- tl.fromTo(slot, anim.from, anim.to);
42
- }
43
-
44
- export function closePopup(petal: PetalElements): void {
45
- const { name, popup, slot, mask } = petal;
46
- const tl = gsap.timeline();
47
-
48
- // VIDEO: Pause any videos inside the popup
49
- pauseVideo(popup);
50
- // SESSION: Store popup closed state
51
- storePopupClosedState(petal);
52
- // Animate the Slot Closed
53
- const anim = getPopupGSAPAnimation(popup, "close");
54
- tl.fromTo(slot, anim.from, anim.to);
55
- // Animate Mask Closed
56
- if (mask) tl.to(mask, animateMaskClosed(0).to, "<");
57
-
58
- // Hide the Popup and clear transforms so they don't persist
59
- tl.set(popup, { display: "none" });
60
- tl.set(slot, { clearProps: "x,y,scale,transform" });
61
- }
62
-
63
- export function initializePopupTriggers(): void {
64
- // Initialize Popup Open Triggers
65
- const openTriggers = getAllPetalElementsOfType(ATTR_PETAL_OPEN);
66
- forEachPopupTrigger(openTriggers, (petal) => {
67
- const { trigger } = petal;
68
- trigger.addEventListener("click", () => openPopup(petal));
69
- });
70
-
71
- // Initialize Popup Close Triggers
72
- const closeTriggers = getAllPetalElementsOfType(ATTR_PETAL_CLOSE);
73
- forEachPopupTrigger(closeTriggers, (petal) => {
74
- const { trigger } = petal;
75
- trigger.addEventListener("click", () => closePopup(petal));
76
- });
77
-
78
- // Initialize Mask Close Triggers (masks with petal-mask-close="true")
79
- const popups = getAllPetalElementsOfType(ATTR_PETAL_POPUP);
80
- popups.forEach((popup) => {
81
- const mask = findPopupElement(popup, "mask") as HTMLElement | null;
82
- const maskClose = popup.getAttribute(ATTR_PETAL_MASK_CLOSE) === "true";
83
- if (mask && maskClose) {
84
- mask.addEventListener("click", () => {
85
- const slot = findPopupElement(popup, "slot") as HTMLElement | null;
86
- const name = popup.getAttribute(ATTR_PETAL_NAME) || popup.id;
87
- if (slot) {
88
- closePopup({ name, popup: popup as HTMLElement, slot, mask, trigger: mask });
89
- }
90
- });
91
- }
92
- });
93
- }
94
-
95
- export function findPetal(el: Element): HTMLElement {
96
- const popupName = el.getAttribute(ATTR_PETAL_NAME);
97
- if (!popupName) throw new MissingNameError(el);
98
-
99
- const popup = document.querySelector(`[${ATTR_PETAL_NAME}='${popupName}'][${ATTR_PETAL_ELEMENT}='${ATTR_PETAL_POPUP}']`) as HTMLElement | null;
100
- if (!popup) throw new MissingPopupError(popupName, el);
101
-
102
- return popup;
103
- }
104
-
105
- export function findPopupElement(popup: Element, attr: string): HTMLElement | null {
106
- return popup.querySelector(`[${ATTR_PETAL_ELEMENT}='${attr}']`);
107
- }
108
-
109
- // Helper to iterate over triggers with error handling
110
- export function forEachPopupTrigger(triggers: NodeListOf<Element>, callback: (petal: PetalElements) => void): void {
111
- triggers.forEach((trigger) => {
112
- try {
113
- const popup = findPetal(trigger);
114
- const name = trigger.getAttribute(ATTR_PETAL_NAME) || "unknown";
115
-
116
- const mask = popup.querySelector(`[${ATTR_PETAL_ELEMENT}='mask']`) as HTMLElement;
117
- if (!mask) throw new MissingMaskError(name, trigger);
118
-
119
- const slot = popup.querySelector(`[${ATTR_PETAL_ELEMENT}='slot']`) as HTMLElement;
120
- if (!slot) throw new MissingSlotError(name, trigger);
121
-
122
- callback({ name, trigger: trigger as HTMLElement, popup, mask, slot });
123
- } catch (error) {
124
- if (error instanceof PetalError) {
125
- // Log and skip invalid triggers
126
- console.error(`[${error.name}]:`, error.message, error.element);
127
- } else {
128
- throw error; // Re-throw unexpected errors
129
- }
130
- }
131
- });
132
- }
package/src/video.ts DELETED
@@ -1,6 +0,0 @@
1
- export function pauseVideo(popup: HTMLElement): void {
2
- // Pause all <video> elements inside the popup before hiding it
3
- popup.querySelectorAll("video").forEach((video) => {
4
- if (!video.paused) video.pause();
5
- });
6
- }
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
- };