defuss 3.4.1 → 3.4.3

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/index.d.ts CHANGED
@@ -137,6 +137,60 @@ declare const T: ({ key, values, tag, ref, ...attrs }: TransProps<string>) => VN
137
137
  type OnHandleRouteChangeFn = (newRoute: string, oldRoute: string) => void;
138
138
  type OnRouteChangeFn = (cb: OnHandleRouteChangeFn) => void;
139
139
  type RouterStrategy = "page-refresh" | "slot-refresh";
140
+ type BeforeUnmountHookFn = () => boolean | void | Promise<boolean | void>;
141
+ type UnmountHookFn = () => void;
142
+ /**
143
+ * Context object passed to components rendered via Route's `component` prop.
144
+ * Provides access to the current route request and lifecycle hooks.
145
+ *
146
+ * @example
147
+ * ```tsx
148
+ * const MyScreen = ({ route }: { route: RouteContext }) => {
149
+ * route.onBeforeUnmount(() => {
150
+ * // Return false to block navigation (e.g. unsaved changes)
151
+ * return confirm("Leave page?");
152
+ * });
153
+ * route.onUnmount(() => {
154
+ * console.log("Route was left");
155
+ * });
156
+ * return <div>Current path: {route.request.path}</div>;
157
+ * };
158
+ * ```
159
+ */
160
+ interface RouteContext {
161
+ /** The matched RouteRequest for the current route */
162
+ request: RouteRequest;
163
+ /**
164
+ * Register a hook that fires before the route is unmounted.
165
+ * Returning `false` (or a Promise resolving to `false`) blocks navigation,
166
+ * allowing implementation of confirmation dialogs.
167
+ */
168
+ onBeforeUnmount(fn: BeforeUnmountHookFn): void;
169
+ /**
170
+ * Register a hook that fires after the route has been unmounted
171
+ * (navigation completed, new route is rendered).
172
+ */
173
+ onUnmount(fn: UnmountHookFn): void;
174
+ }
175
+ /**
176
+ * Props mixin for screen components rendered by `<Route component={...} />`.
177
+ * Extend your component props with this to get typed access to route context.
178
+ *
179
+ * @example
180
+ * ```tsx
181
+ * import { Router, type Props, type RouteProps } from "defuss";
182
+ *
183
+ * export interface ProjectDetailsProps extends Props, RouteProps {}
184
+ *
185
+ * export function ProjectDetailsScreen({ route }: ProjectDetailsProps) {
186
+ * const { projectName } = route.request.params;
187
+ * return <h1>Project: {projectName}</h1>;
188
+ * }
189
+ * ```
190
+ */
191
+ interface RouteProps {
192
+ route: RouteContext;
193
+ }
140
194
  interface RouterConfig {
141
195
  strategy?: RouterStrategy;
142
196
  }
@@ -268,6 +322,10 @@ interface RouterState {
268
322
  pendingResolvers: Array<() => void>;
269
323
  currentPath: string;
270
324
  popAttached: boolean;
325
+ lifecycleHooks: {
326
+ beforeUnmount: Array<BeforeUnmountHookFn>;
327
+ unmount: Array<UnmountHookFn>;
328
+ };
271
329
  }
272
330
  declare global {
273
331
  var __defuss_router__: Router | undefined;
@@ -301,17 +359,49 @@ interface Router {
301
359
  * ```
302
360
  */
303
361
  ready(): Promise<void>;
362
+ /**
363
+ * Create a RouteContext object for a matched route request.
364
+ * The context provides lifecycle hooks (onBeforeUnmount, onUnmount)
365
+ * and is passed to components rendered via Route's `component` prop.
366
+ */
367
+ createRouteContext(request: RouteRequest): RouteContext;
304
368
  }
305
369
  declare const Router: Router;
306
370
 
307
- interface RouteProps extends Props {
371
+ interface RouteComponentProps extends Props {
308
372
  path: string;
309
373
  router?: Router;
310
374
  exact?: boolean;
375
+ /**
376
+ * A component function to render when this route matches.
377
+ * Unlike children (which are eagerly evaluated by the JSX runtime),
378
+ * the component function is called **lazily** — only after the route
379
+ * has been registered and matched. This ensures `Router.getRequest()`
380
+ * returns the correct params inside the component.
381
+ *
382
+ * The component receives a `route` prop (RouteContext) with:
383
+ * - `route.request` — the matched RouteRequest with params, query, etc.
384
+ * - `route.onBeforeUnmount(fn)` — register a hook before route leaves; return `false` to block
385
+ * - `route.onUnmount(fn)` — register a hook after route has been left
386
+ *
387
+ * When the component is async and Route has children, the children are
388
+ * shown as a loading fallback until the async component resolves.
389
+ *
390
+ * @example
391
+ * ```tsx
392
+ * <Route path="/project/:projectName" component={ProjectDetailsScreen} />
393
+ *
394
+ * // With loading fallback for async components:
395
+ * <Route path="/dashboard" component={AsyncDashboard}>
396
+ * <Spinner />
397
+ * </Route>
398
+ * ```
399
+ */
400
+ component?: FC<any>;
311
401
  }
312
- declare const Route: FC<RouteProps>;
402
+ declare const Route: FC<RouteComponentProps>;
313
403
 
314
- interface RedirectProps extends RouteProps {
404
+ interface RedirectProps extends RouteComponentProps {
315
405
  to: string;
316
406
  }
317
407
  declare const Redirect: FC<RedirectProps>;
@@ -396,4 +486,4 @@ declare const Suspense: ({ fallback, ref, children, class: _class, className, id
396
486
  };
397
487
 
398
488
  export { Async, AsyncDefussChild, DOMElement, FC, Globals, NodeType, PersistenceProviderImpl, PersistenceProviderOptions, PersistenceProviderType, Props, Redirect, Ref, RenderInput, Route, Router, RouterSlot, RouterSlotId, Suspense, T, Trans, TransitionConfig, VNode, VNodeAttributes, VNodeChild, addElementEvent, areDomNodesEqual, changeLanguage, checkElementVisibility, clearElementEvents, createI18n, createTrans, domNodeToVNode, getEventMap, getLanguage, getMimeType, getRouterState, htmlStringToVNodes, i18n, inDevMode, isHTML, isMarkup, isSVG, loadLanguage, matchRouteRegistrations, parseDOM, processAllFormElements, queueCallback, removeElementEvent, renderMarkup, replaceDomWithVdom, setupRouter, t, tokenizePath, updateDomWithVdom, waitForDOM, webstorage };
399
- export type { AsyncProps, AsyncState, AsyncStateRef, I18nStore, MatchRouteRegistrationsOpts, OnHandleRouteChangeFn, OnLanguageChangeListener, OnRouteChangeFn, RedirectProps, Replacements, Resolve, RouteHandler, RouteParams, RouteProps, RouteRegistration, RouteRequest, RouterConfig, RouterSlotProps, RouterStrategy, TokenizedPath, TransProps, TransRef, TranslationKeys, TranslationObject, Translations, ValidChild };
489
+ export type { AsyncProps, AsyncState, AsyncStateRef, BeforeUnmountHookFn, I18nStore, MatchRouteRegistrationsOpts, OnHandleRouteChangeFn, OnLanguageChangeListener, OnRouteChangeFn, RedirectProps, Replacements, Resolve, RouteComponentProps, RouteContext, RouteHandler, RouteParams, RouteProps, RouteRegistration, RouteRequest, RouterConfig, RouterSlotProps, RouterStrategy, TokenizedPath, TransProps, TransRef, TranslationKeys, TranslationObject, Translations, UnmountHookFn, ValidChild };