@phillipsharring/graspr-framework 0.1.0 → 0.2.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0
4
+
5
+ ### Added
6
+ - **Lifecycle hooks** — central hook registry for app and page scripts to register callbacks at key points in the page lifecycle. Avoids scattered `htmx:afterSwap` listeners across pages.
7
+ - `onAfterSwap(fn)` — runs after `#app` is swapped via boosted nav
8
+ - `onAfterSettle(fn)` — runs after HTMX settle phase (hx-trigger wired up on new elements)
9
+ - `onPageLoad(fn)` — runs on DOMContentLoaded (full page load only)
10
+ - `onHistoryRestore(fn)` — runs on browser back/forward (history cache restore)
11
+ - Hooks are registered via the barrel export (`import { onAfterSwap } from '@phillipsharring/graspr-framework'`) or via the app namespace (`App.hooks.onAfterSwap(fn)`).
12
+ - `hooks.js` is auto-loaded via `init.js` — no additional imports needed.
13
+
14
+ ## 0.1.0
15
+
16
+ Initial release. Nothing changed, except everything.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phillipsharring/graspr-framework",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "HTMX + Handlebars + Tailwind frontend framework",
5
5
  "type": "module",
6
6
  "exports": {
package/src/hooks.js ADDED
@@ -0,0 +1,69 @@
1
+ // ---------------------------
2
+ // Lifecycle Hooks
3
+ // ---------------------------
4
+ // Central hook registry for app and page scripts to register callbacks
5
+ // that fire at key points in the page lifecycle. Avoids direct
6
+ // htmx:afterSwap / DOMContentLoaded listeners scattered across pages.
7
+ //
8
+ // Usage from app code:
9
+ // import { onAfterSwap } from '@phillipsharring/graspr-framework';
10
+ // onAfterSwap(function(target) { initMyWidget(target); });
11
+ //
12
+ // Usage from inline page scripts:
13
+ // App.hooks.onAfterSwap(function(target) { ... });
14
+
15
+ const hooks = {
16
+ afterSwap: [],
17
+ afterSettle: [],
18
+ pageLoad: [],
19
+ historyRestore: [],
20
+ };
21
+
22
+ var pageLoaded = document.readyState !== 'loading';
23
+
24
+ /** Register a callback that runs after #app is swapped via boosted nav. */
25
+ export function onAfterSwap(fn) {
26
+ hooks.afterSwap.push(fn);
27
+ }
28
+
29
+ /** Register a callback that runs after HTMX settle phase (hx-trigger wired up). */
30
+ export function onAfterSettle(fn) {
31
+ hooks.afterSettle.push(fn);
32
+ }
33
+
34
+ /** Register a callback that runs on DOMContentLoaded (full page load only).
35
+ * If DOMContentLoaded already fired, runs immediately. */
36
+ export function onPageLoad(fn) {
37
+ hooks.pageLoad.push(fn);
38
+ if (pageLoaded) fn(document);
39
+ }
40
+
41
+ /** Register a callback that runs on browser back/forward (history restore). */
42
+ export function onHistoryRestore(fn) {
43
+ hooks.historyRestore.push(fn);
44
+ }
45
+
46
+ // ── Wire up the actual event listeners (one each, calls all registered hooks) ──
47
+
48
+ document.body.addEventListener('htmx:afterSwap', function(e) {
49
+ var target = e.detail?.target;
50
+ if (target && target.id === 'app') {
51
+ hooks.afterSwap.forEach(function(fn) { fn(target); });
52
+ }
53
+ });
54
+
55
+ document.body.addEventListener('htmx:afterSettle', function(e) {
56
+ var target = e.detail?.target;
57
+ if (target && target.id === 'app') {
58
+ hooks.afterSettle.forEach(function(fn) { fn(target); });
59
+ }
60
+ });
61
+
62
+ document.addEventListener('DOMContentLoaded', function() {
63
+ pageLoaded = true;
64
+ hooks.pageLoad.forEach(function(fn) { fn(document); });
65
+ });
66
+
67
+ document.body.addEventListener('htmx:historyRestore', function() {
68
+ hooks.historyRestore.forEach(function(fn) { fn(); });
69
+ });
package/src/index.js CHANGED
@@ -71,3 +71,6 @@ export { escapeHtml } from './helpers/escape-html.js';
71
71
  export { populateSelect } from './helpers/populate-select.js';
72
72
  export { getRouteParams } from './helpers/route-params.js';
73
73
  export { debounce, scrubSearchInput } from './helpers/debounce.js';
74
+
75
+ // Lifecycle hooks
76
+ export { onAfterSwap, onAfterSettle, onPageLoad, onHistoryRestore } from './hooks.js';
package/src/init.js CHANGED
@@ -11,3 +11,4 @@ import './core/auth-state.js';
11
11
  import './core/forms.js';
12
12
  import './core/search.js';
13
13
  import './core/sortable.js';
14
+ import './hooks.js';