snice 2.3.0 → 2.5.0

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.
Files changed (75) hide show
  1. package/README.md +76 -4
  2. package/bin/templates/base/src/main.ts +3 -0
  3. package/bin/templates/base/src/pages/about-page.ts +10 -1
  4. package/bin/templates/base/src/pages/home-page.ts +10 -1
  5. package/bin/templates/base/src/router.ts +3 -2
  6. package/dist/components/drawer/snice-drawer.d.ts +4 -0
  7. package/dist/components/drawer/snice-drawer.js +58 -23
  8. package/dist/components/drawer/snice-drawer.js.map +1 -1
  9. package/dist/components/drawer/snice-drawer.types.d.ts +1 -0
  10. package/dist/components/layout/snice-layout-blog.d.ts +10 -1
  11. package/dist/components/layout/snice-layout-blog.js +47 -8
  12. package/dist/components/layout/snice-layout-blog.js.map +1 -1
  13. package/dist/components/layout/snice-layout-dashboard.d.ts +12 -1
  14. package/dist/components/layout/snice-layout-dashboard.js +92 -13
  15. package/dist/components/layout/snice-layout-dashboard.js.map +1 -1
  16. package/dist/components/layout/snice-layout-landing.d.ts +10 -1
  17. package/dist/components/layout/snice-layout-landing.js +47 -8
  18. package/dist/components/layout/snice-layout-landing.js.map +1 -1
  19. package/dist/components/layout/snice-layout-sidebar.d.ts +13 -1
  20. package/dist/components/layout/snice-layout-sidebar.js +69 -28
  21. package/dist/components/layout/snice-layout-sidebar.js.map +1 -1
  22. package/dist/components/layout/snice-layout.d.ts +9 -1
  23. package/dist/components/layout/snice-layout.js +35 -8
  24. package/dist/components/layout/snice-layout.js.map +1 -1
  25. package/dist/components/layout/snice-layout.types.d.ts +2 -1
  26. package/dist/components/nav/snice-nav.d.ts +16 -0
  27. package/dist/components/nav/snice-nav.js +158 -0
  28. package/dist/components/nav/snice-nav.js.map +1 -0
  29. package/dist/components/nav/snice-nav.types.d.ts +11 -0
  30. package/dist/index.cjs +243 -45
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.esm.js +242 -42
  33. package/dist/index.esm.js.map +1 -1
  34. package/dist/index.iife.js +243 -45
  35. package/dist/index.iife.js.map +1 -1
  36. package/dist/symbols.cjs.map +1 -1
  37. package/dist/symbols.esm.js +8 -2
  38. package/dist/symbols.esm.js.map +1 -1
  39. package/dist/transitions.esm.js +1 -1
  40. package/dist/types/controller.d.ts +1 -1
  41. package/dist/types/element.d.ts +70 -3
  42. package/dist/types/events.d.ts +2 -2
  43. package/dist/types/global.d.ts +1 -1
  44. package/dist/types/index.d.ts +3 -2
  45. package/dist/types/observe.d.ts +1 -1
  46. package/dist/types/request-response.d.ts +2 -2
  47. package/dist/types/router.d.ts +2 -2
  48. package/dist/types/symbols.d.ts +5 -0
  49. package/dist/types/testing.d.ts +1 -1
  50. package/dist/types/transitions.d.ts +1 -1
  51. package/dist/types/types/adopted-options.d.ts +4 -0
  52. package/dist/types/types/app-context.d.ts +81 -0
  53. package/dist/types/types/guard.d.ts +19 -0
  54. package/dist/types/types/index.d.ts +23 -17
  55. package/dist/types/types/moved-options.d.ts +4 -0
  56. package/dist/types/types/{PageOptions.d.ts → page-options.d.ts} +13 -4
  57. package/dist/types/types/placard.d.ts +90 -0
  58. package/dist/types/types/{PropertyOptions.d.ts → property-options.d.ts} +2 -2
  59. package/dist/types/types/route-params.d.ts +21 -0
  60. package/dist/types/types/{RouterInstance.d.ts → router-instance.d.ts} +5 -3
  61. package/dist/types/types/{RouterOptions.d.ts → router-options.d.ts} +1 -1
  62. package/package.json +3 -3
  63. /package/dist/types/types/{DispatchOptions.d.ts → dispatch-options.d.ts} +0 -0
  64. /package/dist/types/types/{IController.d.ts → i-controller.d.ts} +0 -0
  65. /package/dist/types/types/{ObserveOptions.d.ts → observe-options.d.ts} +0 -0
  66. /package/dist/types/types/{OnOptions.d.ts → on-options.d.ts} +0 -0
  67. /package/dist/types/types/{PartOptions.d.ts → part-options.d.ts} +0 -0
  68. /package/dist/types/types/{PropertyConverter.d.ts → property-converter.d.ts} +0 -0
  69. /package/dist/types/types/{QueryOptions.d.ts → query-options.d.ts} +0 -0
  70. /package/dist/types/types/{RequestOptions.d.ts → request-options.d.ts} +0 -0
  71. /package/dist/types/types/{RespondOptions.d.ts → respond-options.d.ts} +0 -0
  72. /package/dist/types/types/{SimpleArray.d.ts → simple-array.d.ts} +0 -0
  73. /package/dist/types/types/{SniceElement.d.ts → snice-element.d.ts} +0 -0
  74. /package/dist/types/types/{SniceGlobal.d.ts → snice-global.d.ts} +0 -0
  75. /package/dist/types/types/{Transition.d.ts → transition.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v2.2.3
2
+ * snice v2.4.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -37,6 +37,7 @@ const CHANNEL_HANDLERS = getSymbol('channel-handlers');
37
37
  const READY_PROMISE = getSymbol('ready-promise');
38
38
  const READY_RESOLVE = getSymbol('ready-resolve');
39
39
  const CONTROLLER = getSymbol('controller');
40
+ const INITIALIZED = getSymbol('initialized');
40
41
  // Event handler symbols
41
42
  const ON_HANDLERS = getSymbol('on-handlers');
42
43
  // Controller symbols
@@ -62,13 +63,18 @@ const CREATED_AT = getSymbol('created-at');
62
63
  // Lifecycle symbols
63
64
  const READY_HANDLERS = getSymbol('ready-handlers');
64
65
  const DISPOSE_HANDLERS = getSymbol('dispose-handlers');
66
+ const MOVED_HANDLERS = getSymbol('moved-handlers');
67
+ const ADOPTED_HANDLERS = getSymbol('adopted-handlers');
65
68
  // Observer symbols
66
69
  const OBSERVERS = getSymbol('observers');
67
70
  // Part symbols
68
71
  const PARTS = getSymbol('parts');
69
72
  const PART_TIMERS = getSymbol('part-timers');
73
+ // Lifecycle callback timers
74
+ const MOVED_TIMERS = getSymbol('moved-timers');
75
+ const ADOPTED_TIMERS = getSymbol('adopted-timers');
70
76
  // Dispatch timing symbols
71
77
  const DISPATCH_TIMERS = getSymbol('dispatch-timers');
72
78
 
73
- export { CHANNEL_HANDLERS, CLEANUP, CONTEXT_REQUEST_HANDLER, CONTROLLER, CONTROLLER_ID, CONTROLLER_KEY, CONTROLLER_NAME_KEY, CONTROLLER_OPERATIONS, CREATED_AT, CURRENT_PAGE_MARKER, DISPATCH_TIMERS, DISPOSE_HANDLERS, EXPLICITLY_SET_PROPERTIES, IS_CONTROLLER_CLASS, IS_CONTROLLER_INSTANCE, IS_ELEMENT_CLASS, NATIVE_CONTROLLER, OBSERVERS, ON_HANDLERS, PAGE_TRANSITION, PARTS, PART_TIMERS, PROPERTIES, PROPERTIES_INITIALIZED, PROPERTY_VALUES, PROPERTY_WATCHERS, READY_HANDLERS, READY_PROMISE, READY_RESOLVE, ROUTER_CONTEXT, getSymbol };
79
+ export { ADOPTED_HANDLERS, ADOPTED_TIMERS, CHANNEL_HANDLERS, CLEANUP, CONTEXT_REQUEST_HANDLER, CONTROLLER, CONTROLLER_ID, CONTROLLER_KEY, CONTROLLER_NAME_KEY, CONTROLLER_OPERATIONS, CREATED_AT, CURRENT_PAGE_MARKER, DISPATCH_TIMERS, DISPOSE_HANDLERS, EXPLICITLY_SET_PROPERTIES, INITIALIZED, IS_CONTROLLER_CLASS, IS_CONTROLLER_INSTANCE, IS_ELEMENT_CLASS, MOVED_HANDLERS, MOVED_TIMERS, NATIVE_CONTROLLER, OBSERVERS, ON_HANDLERS, PAGE_TRANSITION, PARTS, PART_TIMERS, PROPERTIES, PROPERTIES_INITIALIZED, PROPERTY_VALUES, PROPERTY_WATCHERS, READY_HANDLERS, READY_PROMISE, READY_RESOLVE, ROUTER_CONTEXT, getSymbol };
74
80
  //# sourceMappingURL=symbols.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"symbols.esm.js","sources":["../src/global.ts","../src/symbols.ts"],"sourcesContent":[null,null],"names":[],"mappings":";;;;;;AAAA;AACA;AAKA;AACA,SAAS,mBAAmB,GAAA;AAC1B,IAAA,IAAI,CAAE,UAAkB,CAAC,KAAK,EAAE;QAC7B,UAAkB,CAAC,KAAK,GAAG;YAC1B,kBAAkB,EAAE,IAAI,GAAG,EAAE;AAC7B,YAAA,mBAAmB,EAAE,CAAC;YACtB,OAAO,EAAE,IAAI,GAAG;SACjB;IACH;IACA,OAAQ,UAAkB,CAAC,KAAK;AAClC;AAEA;AACO,MAAM,KAAK,GAAG,mBAAmB,EAAE;AAE1C;AACM,SAAU,SAAS,CAAC,IAAY,EAAA;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC5B,QAAA,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACvC;IACA,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAE;AACjC;;AC3BA;AACA;MAMa,mBAAmB,GAAG,SAAS,CAAC,qBAAqB;MACrD,sBAAsB,GAAG,SAAS,CAAC,wBAAwB;MAC3D,gBAAgB,GAAG,SAAS,CAAC,kBAAkB;MAC/C,gBAAgB,GAAG,SAAS,CAAC,kBAAkB;AAE5D;MACa,aAAa,GAAG,SAAS,CAAC,eAAe;MACzC,aAAa,GAAG,SAAS,CAAC,eAAe;MACzC,UAAU,GAAG,SAAS,CAAC,YAAY;AAEhD;MACa,WAAW,GAAG,SAAS,CAAC,aAAa;AAElD;MACa,cAAc,GAAG,SAAS,CAAC,gBAAgB;MAC3C,mBAAmB,GAAG,SAAS,CAAC,iBAAiB;MACjD,aAAa,GAAG,SAAS,CAAC,eAAe;MACzC,qBAAqB,GAAG,SAAS,CAAC,uBAAuB;MACzD,iBAAiB,GAAG,SAAS,CAAC,mBAAmB;AAE9D;MACa,OAAO,GAAG,SAAS,CAAC,SAAS;AAE1C;MACa,UAAU,GAAG,SAAS,CAAC,YAAY;MACnC,eAAe,GAAG,SAAS,CAAC,iBAAiB;MAC7C,sBAAsB,GAAG,SAAS,CAAC,wBAAwB;MAC3D,iBAAiB,GAAG,SAAS,CAAC,mBAAmB;MACjD,yBAAyB,GAAG,SAAS,CAAC,2BAA2B;AAE9E;MACa,cAAc,GAAG,SAAS,CAAC,gBAAgB;MAC3C,mBAAmB,GAAG,SAAS,CAAC,qBAAqB;MACrD,uBAAuB,GAAG,SAAS,CAAC,yBAAyB;MAC7D,eAAe,GAAG,SAAS,CAAC,iBAAiB;MAC7C,UAAU,GAAG,SAAS,CAAC,YAAY;AAEhD;MACa,cAAc,GAAG,SAAS,CAAC,gBAAgB;MAC3C,gBAAgB,GAAG,SAAS,CAAC,kBAAkB;AAE5D;MACa,SAAS,GAAG,SAAS,CAAC,WAAW;AAE9C;MACa,KAAK,GAAG,SAAS,CAAC,OAAO;MACzB,WAAW,GAAG,SAAS,CAAC,aAAa;AAElD;MACa,eAAe,GAAG,SAAS,CAAC,iBAAiB;;;;"}
1
+ {"version":3,"file":"symbols.esm.js","sources":["../src/global.ts","../src/symbols.ts"],"sourcesContent":[null,null],"names":[],"mappings":";;;;;;AAAA;AACA;AAKA;AACA,SAAS,mBAAmB,GAAA;AAC1B,IAAA,IAAI,CAAE,UAAkB,CAAC,KAAK,EAAE;QAC7B,UAAkB,CAAC,KAAK,GAAG;YAC1B,kBAAkB,EAAE,IAAI,GAAG,EAAE;AAC7B,YAAA,mBAAmB,EAAE,CAAC;YACtB,OAAO,EAAE,IAAI,GAAG;SACjB;IACH;IACA,OAAQ,UAAkB,CAAC,KAAK;AAClC;AAEA;AACO,MAAM,KAAK,GAAG,mBAAmB,EAAE;AAE1C;AACM,SAAU,SAAS,CAAC,IAAY,EAAA;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAC5B,QAAA,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACvC;IACA,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAE;AACjC;;AC3BA;AACA;MAMa,mBAAmB,GAAG,SAAS,CAAC,qBAAqB;MACrD,sBAAsB,GAAG,SAAS,CAAC,wBAAwB;MAC3D,gBAAgB,GAAG,SAAS,CAAC,kBAAkB;MAC/C,gBAAgB,GAAG,SAAS,CAAC,kBAAkB;AAE5D;MACa,aAAa,GAAG,SAAS,CAAC,eAAe;MACzC,aAAa,GAAG,SAAS,CAAC,eAAe;MACzC,UAAU,GAAG,SAAS,CAAC,YAAY;MACnC,WAAW,GAAG,SAAS,CAAC,aAAa;AAElD;MACa,WAAW,GAAG,SAAS,CAAC,aAAa;AAElD;MACa,cAAc,GAAG,SAAS,CAAC,gBAAgB;MAC3C,mBAAmB,GAAG,SAAS,CAAC,iBAAiB;MACjD,aAAa,GAAG,SAAS,CAAC,eAAe;MACzC,qBAAqB,GAAG,SAAS,CAAC,uBAAuB;MACzD,iBAAiB,GAAG,SAAS,CAAC,mBAAmB;AAE9D;MACa,OAAO,GAAG,SAAS,CAAC,SAAS;AAE1C;MACa,UAAU,GAAG,SAAS,CAAC,YAAY;MACnC,eAAe,GAAG,SAAS,CAAC,iBAAiB;MAC7C,sBAAsB,GAAG,SAAS,CAAC,wBAAwB;MAC3D,iBAAiB,GAAG,SAAS,CAAC,mBAAmB;MACjD,yBAAyB,GAAG,SAAS,CAAC,2BAA2B;AAE9E;MACa,cAAc,GAAG,SAAS,CAAC,gBAAgB;MAC3C,mBAAmB,GAAG,SAAS,CAAC,qBAAqB;MACrD,uBAAuB,GAAG,SAAS,CAAC,yBAAyB;MAC7D,eAAe,GAAG,SAAS,CAAC,iBAAiB;MAC7C,UAAU,GAAG,SAAS,CAAC,YAAY;AAEhD;MACa,cAAc,GAAG,SAAS,CAAC,gBAAgB;MAC3C,gBAAgB,GAAG,SAAS,CAAC,kBAAkB;MAC/C,cAAc,GAAG,SAAS,CAAC,gBAAgB;MAC3C,gBAAgB,GAAG,SAAS,CAAC,kBAAkB;AAE5D;MACa,SAAS,GAAG,SAAS,CAAC,WAAW;AAE9C;MACa,KAAK,GAAG,SAAS,CAAC,OAAO;MACzB,WAAW,GAAG,SAAS,CAAC,aAAa;AAElD;MACa,YAAY,GAAG,SAAS,CAAC,cAAc;MACvC,cAAc,GAAG,SAAS,CAAC,gBAAgB;AAExD;MACa,eAAe,GAAG,SAAS,CAAC,iBAAiB;;;;"}
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * snice v2.2.3
2
+ * snice v2.4.0
3
3
  * Imperative TypeScript framework for building vanilla web components with decorators, routing, and controllers. No virtual DOM, no build complexity.
4
4
  * (c) 2024
5
5
  * Released under the MIT License.
@@ -1,4 +1,4 @@
1
- import { IController, ControllerClass } from './types/IController';
1
+ import { IController, ControllerClass } from './types/i-controller';
2
2
  declare class ControllerScope {
3
3
  private cleanupFns;
4
4
  private pendingOperations;
@@ -1,6 +1,63 @@
1
- import { QueryOptions } from './types/QueryOptions';
2
- import { PropertyOptions } from './types/PropertyOptions';
3
- import { PartOptions } from './types/PartOptions';
1
+ import { QueryOptions } from './types/query-options';
2
+ import { PropertyOptions } from './types/property-options';
3
+ import { PartOptions } from './types/part-options';
4
+ import { MovedOptions } from './types/moved-options';
5
+ import { AdoptedOptions } from './types/adopted-options';
6
+ import { AppContext } from './types/app-context';
7
+ import { Placard } from './types/placard';
8
+ import { RouteParams } from './types/route-params';
9
+ /**
10
+ * Interface that layout components must implement to receive updates
11
+ * from the router about application state and navigation changes.
12
+ *
13
+ * The framework will call the update method:
14
+ * - When the layout is first created/connected
15
+ * - When route changes occur during navigation
16
+ *
17
+ * Placards are collected at route creation and refreshed before each navigation,
18
+ * ensuring layouts always receive current page metadata.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * @layout('app-shell')
23
+ * class AppShell extends HTMLElement implements Layout {
24
+ * update(appContext: AppContext, placards: Placard[], currentRoute: string, routeParams: RouteParams) {
25
+ * // Update navigation, breadcrumbs, user info, etc.
26
+ * this.renderNavigation(placards, currentRoute);
27
+ * this.updateUserInfo(appContext.principal);
28
+ * this.applyTheme(appContext.theme);
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ export interface Layout {
34
+ /**
35
+ * Called by the framework to update the layout with current application state.
36
+ *
37
+ * @param appContext - Application-wide context (theme, auth, config, etc.)
38
+ * @param placards - All page metadata for navigation and breadcrumbs
39
+ * @param currentRoute - The currently active route path
40
+ * @param routeParams - Parameters extracted from the current route
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * update(appContext, placards, currentRoute, routeParams) {
45
+ * // Filter placards for main navigation
46
+ * const navItems = placards.filter(p => p.show !== false && !p.parent);
47
+ *
48
+ * // Build breadcrumbs for current page
49
+ * const currentPlacard = placards.find(p => matchesRoute(p, currentRoute));
50
+ * const breadcrumbs = this.buildBreadcrumbs(currentPlacard, placards);
51
+ *
52
+ * // Update UI
53
+ * this.renderNavigation(navItems, currentRoute);
54
+ * this.renderBreadcrumbs(breadcrumbs);
55
+ * this.updateUserDisplay(appContext.principal);
56
+ * }
57
+ * ```
58
+ */
59
+ update(appContext: AppContext, placards: Placard[], currentRoute: string, routeParams: RouteParams): void;
60
+ }
4
61
  /**
5
62
  * Applies core element functionality to a constructor
6
63
  * This is shared between @element and @page decorators
@@ -28,6 +85,16 @@ export declare function ready(): (target: any, context: ClassMethodDecoratorCont
28
85
  * Used for cleanup tasks when element is removed from DOM
29
86
  */
30
87
  export declare function dispose(): (target: any, context: ClassMethodDecoratorContext) => void;
88
+ /**
89
+ * Decorator for methods that should run when element is moved within DOM
90
+ * Supports debounce and throttle options to control execution timing
91
+ */
92
+ export declare function moved(options?: MovedOptions): (originalMethod: any, context: ClassMethodDecoratorContext) => (this: HTMLElement, ...args: any[]) => any;
93
+ /**
94
+ * Decorator for methods that should run when element is adopted to new document
95
+ * Supports debounce and throttle options to control execution timing
96
+ */
97
+ export declare function adopted(options?: AdoptedOptions): (originalMethod: any, context: ClassMethodDecoratorContext) => (this: HTMLElement, ...args: any[]) => any;
31
98
  /**
32
99
  * Decorator for methods that render specific parts of the template
33
100
  * Parts are identified by the 'part' attribute in the HTML template
@@ -1,5 +1,5 @@
1
- import { OnOptions } from './types/OnOptions';
2
- import { DispatchOptions } from './types/DispatchOptions';
1
+ import { OnOptions } from './types/on-options';
2
+ import { DispatchOptions } from './types/dispatch-options';
3
3
  export declare function on(eventName: string | string[], selectorOrOptions?: string | OnOptions, options?: OnOptions): (target: any, context: ClassMethodDecoratorContext) => void;
4
4
  export declare function setupEventHandlers(instance: any, element: HTMLElement): void;
5
5
  export declare function cleanupEventHandlers(instance: any): void;
@@ -1,3 +1,3 @@
1
- import { SniceGlobal } from './types/SniceGlobal';
1
+ import { SniceGlobal } from './types/snice-global';
2
2
  export declare const snice: SniceGlobal;
3
3
  export declare function getSymbol(name: string): symbol;
@@ -1,6 +1,7 @@
1
- export { element, layout, property, query, queryAll, watch, context, applyElementFunctionality, ready, dispose, part } from './element';
1
+ export { element, layout, property, query, queryAll, watch, context, applyElementFunctionality, ready, dispose, moved, adopted, part } from './element';
2
+ export type { Layout } from './element';
2
3
  export { Router } from './router';
3
- export { controller, attachController, detachController, getController, useNativeElementControllers, cleanupNativeElementControllers } from './controller';
4
+ export { controller, useNativeElementControllers } from './controller';
4
5
  export { on, dispatch } from './events';
5
6
  export { observe } from './observe';
6
7
  export { request, respond } from './request-response';
@@ -1,4 +1,4 @@
1
- import { ObserveOptions } from './types/ObserveOptions';
1
+ import { ObserveOptions } from './types/observe-options';
2
2
  /**
3
3
  * Decorator for observing external changes like viewport intersection, resize, media queries, and DOM mutations
4
4
  *
@@ -1,5 +1,5 @@
1
- import { RequestOptions } from './types/RequestOptions';
2
- import { RespondOptions } from './types/RespondOptions';
1
+ import { RequestOptions } from './types/request-options';
2
+ import { RespondOptions } from './types/respond-options';
3
3
  /**
4
4
  * Decorator for making requests from elements or controllers.
5
5
  * Uses async generator pattern for bidirectional communication.
@@ -1,5 +1,5 @@
1
- import { RouterOptions } from './types/RouterOptions';
2
- import { RouterInstance } from './types/RouterInstance';
1
+ import { RouterOptions } from './types/router-options';
2
+ import { RouterInstance } from './types/router-instance';
3
3
  /**
4
4
  * Creates a new router instance.
5
5
  * @param {RouterOptions} options - The router configuration options.
@@ -7,6 +7,7 @@ export declare const CHANNEL_HANDLERS: symbol;
7
7
  export declare const READY_PROMISE: symbol;
8
8
  export declare const READY_RESOLVE: symbol;
9
9
  export declare const CONTROLLER: symbol;
10
+ export declare const INITIALIZED: symbol;
10
11
  export declare const ON_HANDLERS: symbol;
11
12
  export declare const CONTROLLER_KEY: symbol;
12
13
  export declare const CONTROLLER_NAME_KEY: symbol;
@@ -26,7 +27,11 @@ export declare const PAGE_TRANSITION: symbol;
26
27
  export declare const CREATED_AT: symbol;
27
28
  export declare const READY_HANDLERS: symbol;
28
29
  export declare const DISPOSE_HANDLERS: symbol;
30
+ export declare const MOVED_HANDLERS: symbol;
31
+ export declare const ADOPTED_HANDLERS: symbol;
29
32
  export declare const OBSERVERS: symbol;
30
33
  export declare const PARTS: symbol;
31
34
  export declare const PART_TIMERS: symbol;
35
+ export declare const MOVED_TIMERS: symbol;
36
+ export declare const ADOPTED_TIMERS: symbol;
32
37
  export declare const DISPATCH_TIMERS: symbol;
@@ -1,4 +1,4 @@
1
1
  export * from './index';
2
- export { registerControllerCleanup, getControllerScope, attachController as attachControllerInternal, detachController as detachControllerInternal } from './controller';
2
+ export { registerControllerCleanup, getControllerScope, attachController, detachController, getController, cleanupNativeElementControllers } from './controller';
3
3
  export { CONTROLLER_KEY, CONTROLLER_OPERATIONS, CONTROLLER_NAME_KEY, CONTROLLER_ID, PROPERTIES_INITIALIZED, PROPERTY_VALUES, PROPERTY_WATCHERS, EXPLICITLY_SET_PROPERTIES, READY_PROMISE, READY_RESOLVE, READY_HANDLERS, DISPOSE_HANDLERS, PARTS, PART_TIMERS, ROUTER_CONTEXT, CONTEXT_REQUEST_HANDLER, PAGE_TRANSITION, CREATED_AT, IS_ELEMENT_CLASS, IS_CONTROLLER_CLASS, IS_CONTROLLER_INSTANCE, NATIVE_CONTROLLER, CLEANUP, ON_HANDLERS, DISPATCH_TIMERS, CHANNEL_HANDLERS, OBSERVERS } from './symbols';
4
4
  export { parseAttributeValue, detectType } from './utils';
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Generic transition system for animating between elements
3
3
  */
4
- import { Transition } from './types/Transition';
4
+ import { Transition } from './types/transition';
5
5
  export type { Transition };
6
6
  /**
7
7
  * Perform a transition between two elements
@@ -0,0 +1,4 @@
1
+ export interface AdoptedOptions {
2
+ throttle?: number;
3
+ debounce?: number;
4
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Application context interface for cross-cutting concerns.
3
+ *
4
+ * This interface defines common application-wide state and services
5
+ * that components, pages, and guards may need to access. All properties
6
+ * are optional, allowing applications to implement only what they need.
7
+ *
8
+ * Applications can extend this interface to add their own context properties:
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * interface MyAppContext extends AppContext {
13
+ * theme: MyThemeService;
14
+ * analytics: AnalyticsService;
15
+ * customProperty: string;
16
+ * }
17
+ * ```
18
+ *
19
+ * The context is typically passed to:
20
+ * - Route guards for access control decisions
21
+ * - Page components via the @context decorator
22
+ * - Placard functions for dynamic metadata
23
+ */
24
+ export interface AppContext {
25
+ /**
26
+ * Theme management and styling context.
27
+ * Typically handles dark/light mode, custom themes, and design tokens.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * theme: {
32
+ * current: 'dark',
33
+ * setTheme: (theme: string) => void,
34
+ * isDarkMode: () => boolean
35
+ * }
36
+ * ```
37
+ */
38
+ theme?: any;
39
+ /**
40
+ * Internationalization and localization context.
41
+ * Handles language switching, translations, and regional formatting.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * locale: {
46
+ * current: 'en-US',
47
+ * setLocale: (locale: string) => void,
48
+ * t: (key: string) => string
49
+ * }
50
+ * ```
51
+ */
52
+ locale?: any;
53
+ /**
54
+ * Authentication and authorization context.
55
+ * Contains user information, roles, permissions, and auth state.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * principal: {
60
+ * user: { id: 1, name: 'John', role: 'admin' },
61
+ * isAuthenticated: () => boolean,
62
+ * hasRole: (role: string) => boolean
63
+ * }
64
+ * ```
65
+ */
66
+ principal?: any;
67
+ /**
68
+ * Application configuration and settings.
69
+ * Runtime configuration, feature flags, API endpoints, etc.
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * config: {
74
+ * apiUrl: 'https://api.example.com',
75
+ * featureFlags: { newUI: true },
76
+ * get: (key: string) => any
77
+ * }
78
+ * ```
79
+ */
80
+ config?: any;
81
+ }
@@ -0,0 +1,19 @@
1
+ import { RouteParams } from './route-params';
2
+ /**
3
+ * Guard function type for route protection and visibility control.
4
+ * Guards determine if navigation to a route should proceed or if a page should be visible.
5
+ *
6
+ * @template T - The context type passed to the guard function
7
+ * @param context - The application context object
8
+ * @param params - Route parameters extracted from the URL
9
+ * @returns boolean - true to allow access, false to deny
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const isAuthenticated: Guard<AppContext> = (ctx, params) => ctx.getUser() !== null;
14
+ * const canEditUser: Guard<AppContext> = (ctx, params) => {
15
+ * return ctx.hasPermission('users.edit', params.id);
16
+ * };
17
+ * ```
18
+ */
19
+ export type Guard<T = any> = (context: T, params: RouteParams) => boolean;
@@ -1,17 +1,23 @@
1
- export * from './QueryOptions';
2
- export * from './PropertyOptions';
3
- export * from './PropertyConverter';
4
- export * from './SniceElement';
5
- export * from './PartOptions';
6
- export * from './SimpleArray';
7
- export * from './RouterOptions';
8
- export * from './PageOptions';
9
- export * from './RouterInstance';
10
- export * from './OnOptions';
11
- export * from './DispatchOptions';
12
- export * from './IController';
13
- export * from './Transition';
14
- export * from './ObserveOptions';
15
- export * from './RequestOptions';
16
- export * from './RespondOptions';
17
- export * from './SniceGlobal';
1
+ export * from './query-options';
2
+ export * from './property-options';
3
+ export * from './property-converter';
4
+ export * from './snice-element';
5
+ export * from './part-options';
6
+ export * from './moved-options';
7
+ export * from './adopted-options';
8
+ export * from './simple-array';
9
+ export * from './router-options';
10
+ export * from './page-options';
11
+ export * from './router-instance';
12
+ export * from './on-options';
13
+ export * from './dispatch-options';
14
+ export * from './i-controller';
15
+ export * from './transition';
16
+ export * from './observe-options';
17
+ export * from './request-options';
18
+ export * from './respond-options';
19
+ export * from './snice-global';
20
+ export * from './placard';
21
+ export * from './guard';
22
+ export * from './route-params';
23
+ export * from './app-context';
@@ -0,0 +1,4 @@
1
+ export interface MovedOptions {
2
+ throttle?: number;
3
+ debounce?: number;
4
+ }
@@ -1,6 +1,7 @@
1
- import { Transition } from './Transition';
2
- export type RouteParams = Record<string, string>;
3
- export type Guard<T = any> = (context: T, params: RouteParams) => boolean | Promise<boolean>;
1
+ import { Transition } from './transition';
2
+ import { Placard } from './placard';
3
+ import { Guard } from './guard';
4
+ import { AppContext } from './app-context';
4
5
  export interface PageOptions {
5
6
  /**
6
7
  * The tag name of the custom element.
@@ -21,10 +22,18 @@ export interface PageOptions {
21
22
  * Guard functions that must pass for navigation to proceed.
22
23
  * Can be a single guard or an array of guards (all must pass).
23
24
  */
24
- guards?: Guard<any> | Guard<any>[];
25
+ guards?: Guard<AppContext> | Guard<AppContext>[];
25
26
  /**
26
27
  * Layout element tag name for this page.
27
28
  * Use false to explicitly disable layout for this page.
28
29
  */
29
30
  layout?: string | false;
31
+ /**
32
+ * Page metadata that layouts can consume for navigation,
33
+ * breadcrumbs, help information, and other UI elements.
34
+ * Can be a static placard object or a function that returns one.
35
+ * @example placard: { name: 'dashboard', title: 'Dashboard' }
36
+ * @example placard: (ctx) => ({ name: 'user-edit', title: `Edit ${ctx.getCurrentUser().name}` })
37
+ */
38
+ placard?: Placard | ((context: AppContext) => Placard);
30
39
  }
@@ -0,0 +1,90 @@
1
+ import { Guard } from './guard';
2
+ /**
3
+ * Placard interface for page metadata that layouts can consume.
4
+ * Provides rich metadata about pages including navigation structure,
5
+ * help information, and dynamic visibility controls.
6
+ */
7
+ export interface Placard<T = any> {
8
+ /**
9
+ * Unique identifier for this placard.
10
+ * Used for referencing in breadcrumbs and parent-child relationships.
11
+ * Should be kebab-case, e.g., 'user-settings', 'admin-dashboard'
12
+ */
13
+ name: string;
14
+ /**
15
+ * Display name shown in navigation and breadcrumbs.
16
+ * Should be concise and descriptive.
17
+ */
18
+ title: string;
19
+ /**
20
+ * Longer description of the page's purpose.
21
+ * Used in tooltips, search results, or help text.
22
+ */
23
+ description?: string;
24
+ /**
25
+ * Visual icon representing the page.
26
+ * Can be emoji, icon font class, or SVG path.
27
+ */
28
+ icon?: string;
29
+ /**
30
+ * Brief help text shown on hover.
31
+ * Explains what the page does or when to use it.
32
+ */
33
+ tooltip?: string;
34
+ /**
35
+ * Additional keywords for search functionality.
36
+ * Helps users discover pages through alternate terms.
37
+ * @example ['settings', 'preferences', 'config', 'options']
38
+ */
39
+ searchTerms?: string[];
40
+ /**
41
+ * Keyboard shortcuts to navigate to this page.
42
+ * Uses standard key notation.
43
+ * @example ['ctrl+d', 'cmd+d', 'alt+shift+d']
44
+ */
45
+ hotkeys?: string[];
46
+ /**
47
+ * Link to detailed documentation or help for this page.
48
+ */
49
+ helpUrl?: string;
50
+ /**
51
+ * Explicitly defined breadcrumb path using placard names.
52
+ * If not provided, breadcrumbs are auto-resolved using parent hierarchy.
53
+ * @example ['dashboard', 'settings', 'advanced-settings']
54
+ */
55
+ breadcrumbs?: string[];
56
+ /**
57
+ * Logical grouping for navigation organization.
58
+ * Pages with the same group are displayed together.
59
+ * @example 'admin', 'reports', 'settings'
60
+ */
61
+ group?: string;
62
+ /**
63
+ * References another placard's name to create hierarchy.
64
+ * Used for nested navigation and breadcrumb construction.
65
+ * @example 'users' // Child of the 'users' page
66
+ */
67
+ parent?: string;
68
+ /**
69
+ * Numeric sort order within the group or parent.
70
+ * Lower numbers appear first.
71
+ */
72
+ order?: number;
73
+ /**
74
+ * Whether to display this page in navigation menus.
75
+ * Defaults to true if not specified.
76
+ */
77
+ show?: boolean;
78
+ /**
79
+ * Guard functions that determine if the page should appear in navigation.
80
+ * Reuses the same guard system as route protection.
81
+ * @example [isAuthenticated, hasAdminRole]
82
+ */
83
+ visibleOn?: Guard<T> | Guard<T>[];
84
+ /**
85
+ * Arbitrary metadata for custom layout needs.
86
+ * Domain-specific or framework-specific data.
87
+ * @example { category: 'reporting', experimental: true, requiredFeatures: ['analytics'] }
88
+ */
89
+ attributes?: Record<string, any>;
90
+ }
@@ -1,5 +1,5 @@
1
- import { SimpleArray } from './SimpleArray';
2
- import { PropertyConverter } from './PropertyConverter';
1
+ import { SimpleArray } from './simple-array';
2
+ import { PropertyConverter } from './property-converter';
3
3
  export interface PropertyOptions {
4
4
  type?: StringConstructor | NumberConstructor | BooleanConstructor | ArrayConstructor | ObjectConstructor | DateConstructor | BigIntConstructor | typeof SimpleArray;
5
5
  attribute?: string | boolean;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Route parameters extracted from URL patterns.
3
+ * Represents dynamic segments in routes as key-value pairs.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * // For route '/users/:userId/posts/:postId'
8
+ * // and URL '/users/123/posts/456'
9
+ * const params: RouteParams = {
10
+ * userId: '123',
11
+ * postId: '456'
12
+ * };
13
+ * ```
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // For non-parameterized routes like '/dashboard'
18
+ * const params: RouteParams = {}; // Empty object
19
+ * ```
20
+ */
21
+ export type RouteParams = Record<string, string>;
@@ -1,10 +1,12 @@
1
- import { PageOptions, Guard } from './PageOptions';
2
- import { Transition } from './Transition';
1
+ import { PageOptions } from './page-options';
2
+ import { Guard } from './guard';
3
+ import { Transition } from './transition';
4
+ import { AppContext } from './app-context';
3
5
  export interface RouterInstance {
4
6
  page: (pageOptions: PageOptions) => <C extends {
5
7
  new (...args: any[]): HTMLElement;
6
8
  }>(constructor: C, context: ClassDecoratorContext) => C;
7
9
  initialize: () => void;
8
10
  navigate: (path: string) => Promise<void>;
9
- register: (route: string, tag: string, transition?: Transition, guards?: Guard<any> | Guard<any>[]) => void;
11
+ register: (route: string, tag: string, transition?: Transition, guards?: Guard<AppContext> | Guard<AppContext>[]) => void;
10
12
  }
@@ -1,4 +1,4 @@
1
- import { Transition } from './Transition';
1
+ import { Transition } from './transition';
2
2
  export interface RouterOptions {
3
3
  /**
4
4
  * The target element selector where the page element will be instantiated.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snice",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "type": "module",
5
5
  "description": "Imperative TypeScript framework for building vanilla web components with decorators, routing, and controllers. No virtual DOM, no build complexity.",
6
6
  "main": "dist/index.cjs",
@@ -80,11 +80,11 @@
80
80
  "build:types": "tsc --project components/tsconfig.json --emitDeclarationOnly",
81
81
  "build:test": "rollup -c rollup.config.test.js",
82
82
  "preview": "vite preview",
83
- "test": "vitest run",
83
+ "test": "npm run build:test && vitest run",
84
84
  "test:watch": "vitest",
85
85
  "test:ui": "vitest --ui",
86
86
  "test:coverage": "vitest --coverage",
87
- "test:src": "vitest run",
87
+ "test:src": "npm run build:test && vitest run",
88
88
  "test:built": "npm run build:test && TEST_BUILT=true vitest run",
89
89
  "test:all": "npm run test:src && npm run test:built",
90
90
  "prerelease": "npm run build",