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.
@@ -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,8 +0,0 @@
1
- import { initializeAllPopups, initializePopupTriggers } from "./popup";
2
- import { initializeBanner } from "./banner";
3
-
4
- console.log(`🌸 Hello from Wellflow Petal v${APP_VERSION}`);
5
-
6
- initializeAllPopups();
7
- initializePopupTriggers();
8
- initializeBanner();
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
- }
@@ -1 +0,0 @@
1
- declare const APP_VERSION: string;
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
- };