@qwickapps/react-framework 1.5.5 → 1.5.6

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 (37) hide show
  1. package/dist/components/QwickApp.d.ts.map +1 -1
  2. package/dist/components/ResponsiveMenu.d.ts.map +1 -1
  3. package/dist/components/Scaffold.d.ts.map +1 -1
  4. package/dist/components/index.d.ts +1 -0
  5. package/dist/components/index.d.ts.map +1 -1
  6. package/dist/contexts/NavigationContext.d.ts +64 -0
  7. package/dist/contexts/NavigationContext.d.ts.map +1 -0
  8. package/dist/contexts/index.d.ts +2 -0
  9. package/dist/contexts/index.d.ts.map +1 -1
  10. package/dist/index.esm.js +142 -55
  11. package/dist/index.js +142 -55
  12. package/dist/palettes/manifest.json +19 -19
  13. package/dist/utils/iconMap.d.ts.map +1 -1
  14. package/dist/utils/reactUtils.d.ts +0 -23
  15. package/dist/utils/reactUtils.d.ts.map +1 -1
  16. package/package.json +1 -1
  17. package/src/components/QwickApp.tsx +16 -14
  18. package/src/components/ResponsiveMenu.tsx +3 -4
  19. package/src/components/Scaffold.tsx +3 -4
  20. package/src/components/index.ts +1 -0
  21. package/src/components/pages/Page.tsx +2 -2
  22. package/src/contexts/NavigationContext.tsx +162 -0
  23. package/src/contexts/index.ts +2 -0
  24. package/src/utils/iconMap.tsx +2 -0
  25. package/src/utils/reactUtils.tsx +2 -47
  26. /package/dist/palettes/{palette-autumn.1.5.5.css → palette-autumn.1.5.6.css} +0 -0
  27. /package/dist/palettes/{palette-autumn.1.5.5.min.css → palette-autumn.1.5.6.min.css} +0 -0
  28. /package/dist/palettes/{palette-cosmic.1.5.5.css → palette-cosmic.1.5.6.css} +0 -0
  29. /package/dist/palettes/{palette-cosmic.1.5.5.min.css → palette-cosmic.1.5.6.min.css} +0 -0
  30. /package/dist/palettes/{palette-default.1.5.5.css → palette-default.1.5.6.css} +0 -0
  31. /package/dist/palettes/{palette-default.1.5.5.min.css → palette-default.1.5.6.min.css} +0 -0
  32. /package/dist/palettes/{palette-ocean.1.5.5.css → palette-ocean.1.5.6.css} +0 -0
  33. /package/dist/palettes/{palette-ocean.1.5.5.min.css → palette-ocean.1.5.6.min.css} +0 -0
  34. /package/dist/palettes/{palette-spring.1.5.5.css → palette-spring.1.5.6.css} +0 -0
  35. /package/dist/palettes/{palette-spring.1.5.5.min.css → palette-spring.1.5.6.min.css} +0 -0
  36. /package/dist/palettes/{palette-winter.1.5.5.css → palette-winter.1.5.6.css} +0 -0
  37. /package/dist/palettes/{palette-winter.1.5.5.min.css → palette-winter.1.5.6.min.css} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"QwickApp.d.ts","sourceRoot":"","sources":["../../src/components/QwickApp.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAiC,MAAM,OAAO,CAAC;AACtD,OAAO,EAAkD,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAmB,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC7G,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,gBAAgB,CAAC;AAQxB,UAAU,sBAAuB,SAAQ,aAAa;IACpD,yDAAyD;IACzD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,2CAA2C;IAC3C,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,8CAA8C;IAC9C,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CAEpB;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA+GrD,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,oBAM9B,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"QwickApp.d.ts","sourceRoot":"","sources":["../../src/components/QwickApp.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAiC,MAAM,OAAO,CAAC;AACtD,OAAO,EAAsE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACjH,OAAO,EAAmB,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC7G,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,gBAAgB,CAAC;AAQxB,UAAU,sBAAuB,SAAQ,aAAa;IACpD,yDAAyD;IACzD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,2CAA2C;IAC3C,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,8CAA8C;IAC9C,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,sBAAsB,CAAC;IACpC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CAEpB;AAED,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAiHrD,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,oBAM9B,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ResponsiveMenu.d.ts","sourceRoot":"","sources":["../../src/components/ResponsiveMenu.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,aAAa,EAAoC,MAAM,uBAAuB,CAAC;AAIxF,OAAO,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,qCAAqC;IACrC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC3C,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C;AAID,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA+QjD,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"ResponsiveMenu.d.ts","sourceRoot":"","sources":["../../src/components/ResponsiveMenu.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,aAAa,EAAoC,MAAM,uBAAuB,CAAC;AAIxF,OAAO,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,qCAAqC;IACrC,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC3C,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C;AAID,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA8QjD,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Scaffold.d.ts","sourceRoot":"","sources":["../../src/components/Scaffold.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAOnD,OAAO,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,+BAA+B;IAC/B,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC5B,4BAA4B;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAWD,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAsarC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"Scaffold.d.ts","sourceRoot":"","sources":["../../src/components/Scaffold.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAOnD,OAAO,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAIhD,MAAM,WAAW,WAAW;IAC1B,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,+BAA+B;IAC/B,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC5B,4BAA4B;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mEAAmE;IACnE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAWD,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAqarC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -22,6 +22,7 @@ export * from './layout';
22
22
  export * from './pages';
23
23
  export { default as Scaffold } from './Scaffold';
24
24
  export type { ScaffoldProps, AppBarProps } from './Scaffold';
25
+ export type { MenuItem } from './menu/MenuItem';
25
26
  export { default as ResponsiveMenu } from './ResponsiveMenu';
26
27
  export type { ResponsiveMenuProps } from './ResponsiveMenu';
27
28
  export * from './QwickApp';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,kCAAkC,CAAC;AAC1C,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAG9B,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC7E,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,kCAAkC,CAAC;AAC1C,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAG9B,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAC7E,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Navigation Context - Smart navigation that auto-detects React Router
3
+ *
4
+ * Provides navigation functions that work with React Router when available,
5
+ * falling back to window.location for non-router apps or SSR.
6
+ *
7
+ * Usage:
8
+ * - Wrap your app with NavigationProvider (done automatically by QwickApp)
9
+ * - Use useNavigation() hook to get navigate function and location
10
+ *
11
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
12
+ */
13
+ import { type ReactNode } from 'react';
14
+ /**
15
+ * Location type matching React Router's location shape
16
+ */
17
+ export interface NavigationLocation {
18
+ pathname: string;
19
+ search: string;
20
+ hash: string;
21
+ }
22
+ /**
23
+ * Navigate function type
24
+ */
25
+ export type NavigateFunction = (to: string | number) => void;
26
+ /**
27
+ * Navigation context value
28
+ */
29
+ export interface NavigationContextValue {
30
+ navigate: NavigateFunction;
31
+ location: NavigationLocation | undefined;
32
+ }
33
+ /**
34
+ * Smart Navigation Provider
35
+ *
36
+ * Automatically detects if the app is inside a React Router context:
37
+ * - If inside Router: uses React Router's useNavigate/useLocation (respects basename)
38
+ * - If outside Router: falls back to window.location
39
+ *
40
+ * This is included automatically by QwickApp - you don't need to add it manually.
41
+ */
42
+ export declare function NavigationProvider({ children }: {
43
+ children: ReactNode;
44
+ }): import("react/jsx-runtime").JSX.Element;
45
+ /**
46
+ * Hook to access navigation functions
47
+ *
48
+ * @returns Object containing navigate function and current location
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * function MyComponent() {
53
+ * const { navigate, location } = useNavigation();
54
+ *
55
+ * const handleClick = () => {
56
+ * navigate('/dashboard');
57
+ * };
58
+ *
59
+ * return <button onClick={handleClick}>Go to Dashboard</button>;
60
+ * }
61
+ * ```
62
+ */
63
+ export declare function useNavigation(): NavigationContextValue;
64
+ //# sourceMappingURL=NavigationContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationContext.d.ts","sourceRoot":"","sources":["../../src/contexts/NavigationContext.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAOlE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAC1C;AAmED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAcvE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,IAAI,sBAAsB,CAWtD"}
@@ -2,6 +2,8 @@ export { DataProvider, t, T, useData, useDataContext, useDataProvider, useResolv
2
2
  export type { DataProviderProps } from './DataContext';
3
3
  export { DimensionsProvider, useDimensions } from './DimensionsContext';
4
4
  export type { DimensionsContextValue, DimensionTokens } from './DimensionsContext';
5
+ export { NavigationProvider, useNavigation } from './NavigationContext';
6
+ export type { NavigateFunction, NavigationContextValue, NavigationLocation } from './NavigationContext';
5
7
  export { PaletteProvider, usePalette } from './PaletteContext';
6
8
  export type { PaletteConfig, PaletteContextValue } from './PaletteContext';
7
9
  export { ThemeProvider, useTheme } from './ThemeContext';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contexts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9H,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxE,YAAY,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACrE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contexts/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC9H,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxE,YAAY,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxE,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC/D,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACrE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.esm.js CHANGED
@@ -4,10 +4,11 @@ import { useMediaQuery, Box, useTheme as useTheme$1, Paper, Typography, Tooltip,
4
4
  import React, { useMemo, useContext, useState, useCallback, useEffect, createContext, useReducer, useRef, isValidElement, createElement, useId, useLayoutEffect, Component, cloneElement } from 'react';
5
5
  import { MustacheTemplateProvider, MemoryCacheProvider, CachedDataProvider, Field, Editor, FieldType, Schema, Model, DataType } from '@qwickapps/schema';
6
6
  import { createTheme, ThemeProvider as ThemeProvider$1 } from '@mui/material/styles';
7
- import { Check, ContentCopy, Home, Menu, Dashboard, Info, Help, Book, Email, Phone, Send, Add, Edit, Delete, Save, Close, ArrowForward, ArrowBack, Search, Share, Download, CloudDownload, CloudUpload, Person, Group, Favorite, Star, VerifiedUser, Business, ShoppingCart, AttachMoney, Lock, LockOpen, Visibility, VisibilityOff, Settings, Computer, Article as Article$1, Inventory, Inventory2, Speed, SupportAgent, Tune, Code as Code$1, Psychology, Autorenew, IntegrationInstructions, Construction, Work, Layers, TrendingUp, Route, Sync, Architecture, Security, Key, VpnKey, PersonSearch, ManageAccounts, Storage, Refresh, Block, CheckCircle, RotateRight, Memory, BrokenImage, MoreVert, FormatBold, FormatItalic, FormatUnderlined, ExpandMore, ExpandLess, Schedule, Launch, LightMode, DarkMode, SettingsSystemDaydream, Palette, Circle, RadioButtonUnchecked } from '@mui/icons-material';
7
+ import { Check, ContentCopy, Home, Menu, Dashboard, Info, Help, Book, Email, Phone, Send, Add, Edit, Delete, Save, Close, ArrowForward, ArrowBack, Search, Share, Download, CloudDownload, CloudUpload, Person, Group, Favorite, Star, VerifiedUser, Business, ShoppingCart, AttachMoney, Lock, LockOpen, Visibility, VisibilityOff, Settings, Computer, Article as Article$1, Inventory, Inventory2, Speed, SupportAgent, Tune, Code as Code$1, Psychology, Autorenew, IntegrationInstructions, Construction, Work, Layers, TrendingUp, Route, Sync, Architecture, Security, Key, VpnKey, PersonSearch, ManageAccounts, Storage, Refresh, Block, CheckCircle, RotateRight, Memory, LocalOffer, BrokenImage, MoreVert, FormatBold, FormatItalic, FormatUnderlined, ExpandMore, ExpandLess, Schedule, Launch, LightMode, DarkMode, SettingsSystemDaydream, Palette, Circle, RadioButtonUnchecked } from '@mui/icons-material';
8
8
  import { IsOptional, ValidateIf, IsIn, IsInt, Min, IsString, IsNotEmpty, IsBoolean, IsNumber, Max, IsArray, ValidateNested, IsUrl, IsObject } from 'class-validator';
9
9
  import 'reflect-metadata';
10
10
  import { Type } from 'class-transformer';
11
+ import { UNSAFE_NavigationContext, useNavigate, useLocation } from 'react-router-dom';
11
12
 
12
13
  /**
13
14
  * Breakpoint utilities for QwickApps React Framework
@@ -3384,6 +3385,10 @@ const iconMap = {
3384
3385
  memory: {
3385
3386
  emoji: '🧠',
3386
3387
  component: Memory
3388
+ },
3389
+ local_offer: {
3390
+ emoji: '🏷️',
3391
+ component: LocalOffer
3387
3392
  }
3388
3393
  };
3389
3394
  /**
@@ -4815,41 +4820,6 @@ var FormBlockModel$1 = FormBlockModel;
4815
4820
  *
4816
4821
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
4817
4822
  */
4818
- /**
4819
- * Get the current location from browser or undefined in SSR
4820
- * Works without relying on routing libraries
4821
- * @returns {object | undefined} - The location object if in browser, otherwise undefined
4822
- */
4823
- const useSafeLocation = () => {
4824
- // Use browser location if available (works in any React app)
4825
- if (typeof window !== 'undefined') {
4826
- return {
4827
- pathname: window.location.pathname,
4828
- search: window.location.search,
4829
- hash: window.location.hash
4830
- };
4831
- }
4832
- return undefined;
4833
- };
4834
- /**
4835
- * Get a navigation function with fallback to window.location
4836
- * Works without relying on routing libraries
4837
- * @returns {NavigateFunction} - The navigate function
4838
- */
4839
- const useSafeNavigate = () => {
4840
- // Return function that uses window.location
4841
- return to => {
4842
- if (typeof to === 'string') {
4843
- if (typeof window !== 'undefined') {
4844
- window.location.href = to;
4845
- }
4846
- } else if (typeof to === 'number') {
4847
- if (typeof window !== 'undefined' && window.history) {
4848
- window.history.go(to);
4849
- }
4850
- }
4851
- };
4852
- };
4853
4823
  /**
4854
4824
  * Extract text content from ReactNode for code processing
4855
4825
  * Handles natural React usage like <Code>const x = 1;</Code>
@@ -23386,6 +23356,115 @@ const useDimensions = () => {
23386
23356
  return context;
23387
23357
  };
23388
23358
 
23359
+ const NavigationContext = /*#__PURE__*/createContext(null);
23360
+ /**
23361
+ * Internal provider that uses React Router hooks
23362
+ * Only rendered when we're inside a Router context
23363
+ */
23364
+ function ReactRouterNavigationProvider({
23365
+ children
23366
+ }) {
23367
+ const reactRouterNavigate = useNavigate();
23368
+ const reactRouterLocation = useLocation();
23369
+ const navigate = to => {
23370
+ if (typeof to === 'string') {
23371
+ reactRouterNavigate(to);
23372
+ } else if (typeof to === 'number') {
23373
+ reactRouterNavigate(to);
23374
+ }
23375
+ };
23376
+ return jsx(NavigationContext.Provider, {
23377
+ value: {
23378
+ navigate,
23379
+ location: {
23380
+ pathname: reactRouterLocation.pathname,
23381
+ search: reactRouterLocation.search,
23382
+ hash: reactRouterLocation.hash
23383
+ }
23384
+ },
23385
+ children: children
23386
+ });
23387
+ }
23388
+ /**
23389
+ * Internal provider that uses window.location fallback
23390
+ * Used when not inside a React Router context
23391
+ */
23392
+ function FallbackNavigationProvider({
23393
+ children
23394
+ }) {
23395
+ const navigate = to => {
23396
+ if (typeof window === 'undefined') return;
23397
+ if (typeof to === 'string') {
23398
+ window.location.href = to;
23399
+ } else if (typeof to === 'number') {
23400
+ window.history.go(to);
23401
+ }
23402
+ };
23403
+ const location = typeof window !== 'undefined' ? {
23404
+ pathname: window.location.pathname,
23405
+ search: window.location.search,
23406
+ hash: window.location.hash
23407
+ } : undefined;
23408
+ return jsx(NavigationContext.Provider, {
23409
+ value: {
23410
+ navigate,
23411
+ location
23412
+ },
23413
+ children: children
23414
+ });
23415
+ }
23416
+ /**
23417
+ * Smart Navigation Provider
23418
+ *
23419
+ * Automatically detects if the app is inside a React Router context:
23420
+ * - If inside Router: uses React Router's useNavigate/useLocation (respects basename)
23421
+ * - If outside Router: falls back to window.location
23422
+ *
23423
+ * This is included automatically by QwickApp - you don't need to add it manually.
23424
+ */
23425
+ function NavigationProvider({
23426
+ children
23427
+ }) {
23428
+ // Check if we're inside a React Router by checking its internal context
23429
+ // useContext doesn't throw - it returns null if the context doesn't exist
23430
+ const routerContext = useContext(UNSAFE_NavigationContext);
23431
+ if (routerContext) {
23432
+ // We're inside a Router, use React Router's navigation
23433
+ return jsx(ReactRouterNavigationProvider, {
23434
+ children: children
23435
+ });
23436
+ }
23437
+ // Not inside a Router, use window.location fallback
23438
+ return jsx(FallbackNavigationProvider, {
23439
+ children: children
23440
+ });
23441
+ }
23442
+ /**
23443
+ * Hook to access navigation functions
23444
+ *
23445
+ * @returns Object containing navigate function and current location
23446
+ *
23447
+ * @example
23448
+ * ```tsx
23449
+ * function MyComponent() {
23450
+ * const { navigate, location } = useNavigation();
23451
+ *
23452
+ * const handleClick = () => {
23453
+ * navigate('/dashboard');
23454
+ * };
23455
+ *
23456
+ * return <button onClick={handleClick}>Go to Dashboard</button>;
23457
+ * }
23458
+ * ```
23459
+ */
23460
+ function useNavigation() {
23461
+ const context = useContext(NavigationContext);
23462
+ if (!context) {
23463
+ throw new Error('useNavigation must be used within a NavigationProvider. ' + 'Make sure your component is wrapped in QwickApp or NavigationProvider.');
23464
+ }
23465
+ return context;
23466
+ }
23467
+
23389
23468
  /**
23390
23469
  * Schema for PaletteSwitcher component - Color palette switching control
23391
23470
  *
@@ -24533,7 +24612,9 @@ const PageView = ({
24533
24612
  };
24534
24613
  }, [isPrintMode, printConfig]);
24535
24614
  // Route (fallback to current location)
24536
- const location = useSafeLocation();
24615
+ const {
24616
+ location
24617
+ } = useNavigation();
24537
24618
  const actualRoute = resolved.route || location?.pathname || '';
24538
24619
  // Context value
24539
24620
  const contextValue = useMemo(() => ({
@@ -24648,9 +24729,11 @@ const Scaffold = ({
24648
24729
  const [isDrawerOpen, setIsDrawerOpen] = useState(false);
24649
24730
  const [isRailExpanded, setIsRailExpanded] = useState(false);
24650
24731
  const [isMounted, setIsMounted] = useState(false);
24651
- // React Router hooks (if available)
24652
- const location = useSafeLocation();
24653
- const navigate = useSafeNavigate();
24732
+ // Navigation (uses React Router if available, falls back to window.location)
24733
+ const {
24734
+ navigate,
24735
+ location
24736
+ } = useNavigation();
24654
24737
  const currentPath = isMounted ? location?.pathname : undefined;
24655
24738
  // Debug logging for navigation
24656
24739
  React.useEffect(() => {
@@ -25019,9 +25102,11 @@ const ResponsiveMenu = props => {
25019
25102
  appName,
25020
25103
  logo: contextLogo
25021
25104
  } = useQwickApp$1();
25022
- // React Router hooks (if available)
25023
- const navigate = useSafeNavigate();
25024
- const location = useSafeLocation();
25105
+ // Navigation (uses React Router if available, falls back to window.location)
25106
+ const {
25107
+ navigate,
25108
+ location
25109
+ } = useNavigation();
25025
25110
  const currentPath = location?.pathname;
25026
25111
  // Debug logging
25027
25112
  React.useEffect(() => {
@@ -25923,17 +26008,19 @@ const QwickApp = ({
25923
26008
  }) : content;
25924
26009
  const appContent = jsx(ErrorBoundary, {
25925
26010
  children: jsx(AccessibilityProvider, {
25926
- children: jsx("div", {
25927
- className: `qwick-app ${className || ''}`,
25928
- style: style,
25929
- children: jsx(ThemeProvider, {
25930
- appId: resolvedConfig.appId,
25931
- defaultTheme: resolvedConfig.defaultTheme,
25932
- defaultPalette: resolvedConfig.defaultPalette,
25933
- children: jsx(QwickAppContext.Provider, {
25934
- value: contextValue,
25935
- children: jsx(PrintModeProvider, {
25936
- children: wrappedContent
26011
+ children: jsx(NavigationProvider, {
26012
+ children: jsx("div", {
26013
+ className: `qwick-app ${className || ''}`,
26014
+ style: style,
26015
+ children: jsx(ThemeProvider, {
26016
+ appId: resolvedConfig.appId,
26017
+ defaultTheme: resolvedConfig.defaultTheme,
26018
+ defaultPalette: resolvedConfig.defaultPalette,
26019
+ children: jsx(QwickAppContext.Provider, {
26020
+ value: contextValue,
26021
+ children: jsx(PrintModeProvider, {
26022
+ children: wrappedContent
26023
+ })
25937
26024
  })
25938
26025
  })
25939
26026
  })
@@ -31808,4 +31895,4 @@ __decorate([Field({
31808
31895
  }), IsOptional(), __metadata("design:type", Boolean)], PageTemplateSchema.prototype, "indexable", void 0);
31809
31896
  PageTemplateSchema = __decorate([Schema('PageTemplate', '1.0.0')], PageTemplateSchema);
31810
31897
 
31811
- export { AVAILABLE_PALETTES, AccessibilityProvider, ActionModel, ActionType, AllPalettes, AppConfig, AppConfigBuilder, Article, ArticleModel, Breadcrumbs, Button, Captcha, CardListGrid, CardListGridModel, ChoiceInputField, ChoiceInputFieldModel, Code, CodeModel, CollapsibleLayout, CollapsibleLayoutView, ComponentTransformer$1 as ComponentTransformer, Container$8 as Container, Content, ContentModel, CoverImageHeader, CoverImageHeaderModel, DataProvider, DataProxy, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, DimensionsProvider, ErrorBoundary, FeatureCard, FeatureCardActionModel, FeatureCardModel, FeatureGrid, FeatureGridModel, FeatureItemModel, Footer, FooterItemModel, FooterModel, FooterSectionModel, FormBlock, FormBlockModel, FormCheckbox, FormField, FormMethod, FormPage, FormSelect, GridCell, GridCellModel, GridLayout, GridLayoutModel, HeaderActionModel, HeroBlock, HeroBlockModel, Html, HtmlInputField, HtmlModel, Image, ImageModel, Logo, Markdown, MarkdownModel, MetadataItemModel, ModelView, Page, PageBannerHeader, PageBannerHeaderModel, PageTemplateSchema, PaletteAutumn, PaletteCosmic, PaletteDefault, PaletteOcean, PaletteProvider, PaletteSpring, PaletteSwitcher, PaletteSwitcherModel, PaletteWinter, PrintConfigSchema, PrintModeProvider, ProductCard, ProductCardActionModel, ProductCardModel, ProductLogo, ProductModel, QWICKAPP_COMPONENT, QwickApp, QwickAppsLogo, QwickIcon, ResponsiveMenu, SafeSpan, SafeSpanModel, Scaffold, Section, SectionModel, SelectInputField, SwitchInputField, T, Text$1 as Text, TextField, TextInputField, TextInputFieldModel, TextModel, ThemeProvider, ThemeSwitcher, ThemeSwitcherModel, ViewSchema, animationConfigs, applyCustomPalette, clearManifestCache, clearPaletteCache, clearUserPalettePreference, clearUserThemePreference, configurePaletteLoader, createAppConfig, createModelViewClass, createPaletteFromCurrentTheme, createSerializableView, defaultCollapsibleLayoutProps, deleteCustomPalette, exportPalette, extractTextFromReactNode, getAvailablePalettes, getCSSVariable, getComputedTheme, getCurrentPalette, getCurrentTheme, getCustomPalettes, getIconComponent, getIconEmoji, getLogger, getPaletteConfig, getPaletteFromManifest, getPaletteName, getRegisteredIcons, getSystemTheme, getThemePerformanceStats, hasIcon, iconMap, importPalette, initializePalette, initializeTheme, isCollapsibleLayoutProps, isPaletteLoaded, loadPalette, loadPaletteManifest, loadUserPalettePreference, loadUserThemePreference, logThemePerformanceStats, loggers, preloadPalettes, registerCustomPalette, registerIcon, resetThemePerformanceStats, resolveDimension, resolveDimensions, resolveSpacing, resolveSpacingProps, saveCustomPalette, savePalettePreference, saveThemePreference, saveUserPalettePreference, saveUserThemePreference, setCSSVariable, setPalette, setTheme, spacingConfigs, t, toCssLength, useAccessibility, useBaseProps, useBreadcrumbs, useCollapsibleState, useData, useDataBinding, useDataContext, useDataProvider, useDimensions, usePageContext, usePalette, usePrintMode$1 as usePrintMode, usePrintMode as usePrintModeHook, useQwickApp, useResolveTemplate, useSafeLocation, useSafeNavigate, useTemplate, useTheme, withAccessibility, withErrorBoundary };
31898
+ export { AVAILABLE_PALETTES, AccessibilityProvider, ActionModel, ActionType, AllPalettes, AppConfig, AppConfigBuilder, Article, ArticleModel, Breadcrumbs, Button, Captcha, CardListGrid, CardListGridModel, ChoiceInputField, ChoiceInputFieldModel, Code, CodeModel, CollapsibleLayout, CollapsibleLayoutView, ComponentTransformer$1 as ComponentTransformer, Container$8 as Container, Content, ContentModel, CoverImageHeader, CoverImageHeaderModel, DataProvider, DataProxy, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, DimensionsProvider, ErrorBoundary, FeatureCard, FeatureCardActionModel, FeatureCardModel, FeatureGrid, FeatureGridModel, FeatureItemModel, Footer, FooterItemModel, FooterModel, FooterSectionModel, FormBlock, FormBlockModel, FormCheckbox, FormField, FormMethod, FormPage, FormSelect, GridCell, GridCellModel, GridLayout, GridLayoutModel, HeaderActionModel, HeroBlock, HeroBlockModel, Html, HtmlInputField, HtmlModel, Image, ImageModel, Logo, Markdown, MarkdownModel, MetadataItemModel, ModelView, NavigationProvider, Page, PageBannerHeader, PageBannerHeaderModel, PageTemplateSchema, PaletteAutumn, PaletteCosmic, PaletteDefault, PaletteOcean, PaletteProvider, PaletteSpring, PaletteSwitcher, PaletteSwitcherModel, PaletteWinter, PrintConfigSchema, PrintModeProvider, ProductCard, ProductCardActionModel, ProductCardModel, ProductLogo, ProductModel, QWICKAPP_COMPONENT, QwickApp, QwickAppsLogo, QwickIcon, ResponsiveMenu, SafeSpan, SafeSpanModel, Scaffold, Section, SectionModel, SelectInputField, SwitchInputField, T, Text$1 as Text, TextField, TextInputField, TextInputFieldModel, TextModel, ThemeProvider, ThemeSwitcher, ThemeSwitcherModel, ViewSchema, animationConfigs, applyCustomPalette, clearManifestCache, clearPaletteCache, clearUserPalettePreference, clearUserThemePreference, configurePaletteLoader, createAppConfig, createModelViewClass, createPaletteFromCurrentTheme, createSerializableView, defaultCollapsibleLayoutProps, deleteCustomPalette, exportPalette, extractTextFromReactNode, getAvailablePalettes, getCSSVariable, getComputedTheme, getCurrentPalette, getCurrentTheme, getCustomPalettes, getIconComponent, getIconEmoji, getLogger, getPaletteConfig, getPaletteFromManifest, getPaletteName, getRegisteredIcons, getSystemTheme, getThemePerformanceStats, hasIcon, iconMap, importPalette, initializePalette, initializeTheme, isCollapsibleLayoutProps, isPaletteLoaded, loadPalette, loadPaletteManifest, loadUserPalettePreference, loadUserThemePreference, logThemePerformanceStats, loggers, preloadPalettes, registerCustomPalette, registerIcon, resetThemePerformanceStats, resolveDimension, resolveDimensions, resolveSpacing, resolveSpacingProps, saveCustomPalette, savePalettePreference, saveThemePreference, saveUserPalettePreference, saveUserThemePreference, setCSSVariable, setPalette, setTheme, spacingConfigs, t, toCssLength, useAccessibility, useBaseProps, useBreadcrumbs, useCollapsibleState, useData, useDataBinding, useDataContext, useDataProvider, useDimensions, useNavigation, usePageContext, usePalette, usePrintMode$1 as usePrintMode, usePrintMode as usePrintModeHook, useQwickApp, useResolveTemplate, useTemplate, useTheme, withAccessibility, withErrorBoundary };
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ var iconsMaterial = require('@mui/icons-material');
10
10
  var classValidator = require('class-validator');
11
11
  require('reflect-metadata');
12
12
  var classTransformer = require('class-transformer');
13
+ var reactRouterDom = require('react-router-dom');
13
14
 
14
15
  /**
15
16
  * Breakpoint utilities for QwickApps React Framework
@@ -3386,6 +3387,10 @@ const iconMap = {
3386
3387
  memory: {
3387
3388
  emoji: '🧠',
3388
3389
  component: iconsMaterial.Memory
3390
+ },
3391
+ local_offer: {
3392
+ emoji: '🏷️',
3393
+ component: iconsMaterial.LocalOffer
3389
3394
  }
3390
3395
  };
3391
3396
  /**
@@ -4817,41 +4822,6 @@ var FormBlockModel = exports.FormBlockModel;
4817
4822
  *
4818
4823
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
4819
4824
  */
4820
- /**
4821
- * Get the current location from browser or undefined in SSR
4822
- * Works without relying on routing libraries
4823
- * @returns {object | undefined} - The location object if in browser, otherwise undefined
4824
- */
4825
- const useSafeLocation = () => {
4826
- // Use browser location if available (works in any React app)
4827
- if (typeof window !== 'undefined') {
4828
- return {
4829
- pathname: window.location.pathname,
4830
- search: window.location.search,
4831
- hash: window.location.hash
4832
- };
4833
- }
4834
- return undefined;
4835
- };
4836
- /**
4837
- * Get a navigation function with fallback to window.location
4838
- * Works without relying on routing libraries
4839
- * @returns {NavigateFunction} - The navigate function
4840
- */
4841
- const useSafeNavigate = () => {
4842
- // Return function that uses window.location
4843
- return to => {
4844
- if (typeof to === 'string') {
4845
- if (typeof window !== 'undefined') {
4846
- window.location.href = to;
4847
- }
4848
- } else if (typeof to === 'number') {
4849
- if (typeof window !== 'undefined' && window.history) {
4850
- window.history.go(to);
4851
- }
4852
- }
4853
- };
4854
- };
4855
4825
  /**
4856
4826
  * Extract text content from ReactNode for code processing
4857
4827
  * Handles natural React usage like <Code>const x = 1;</Code>
@@ -23388,6 +23358,115 @@ const useDimensions = () => {
23388
23358
  return context;
23389
23359
  };
23390
23360
 
23361
+ const NavigationContext = /*#__PURE__*/React.createContext(null);
23362
+ /**
23363
+ * Internal provider that uses React Router hooks
23364
+ * Only rendered when we're inside a Router context
23365
+ */
23366
+ function ReactRouterNavigationProvider({
23367
+ children
23368
+ }) {
23369
+ const reactRouterNavigate = reactRouterDom.useNavigate();
23370
+ const reactRouterLocation = reactRouterDom.useLocation();
23371
+ const navigate = to => {
23372
+ if (typeof to === 'string') {
23373
+ reactRouterNavigate(to);
23374
+ } else if (typeof to === 'number') {
23375
+ reactRouterNavigate(to);
23376
+ }
23377
+ };
23378
+ return jsxRuntime.jsx(NavigationContext.Provider, {
23379
+ value: {
23380
+ navigate,
23381
+ location: {
23382
+ pathname: reactRouterLocation.pathname,
23383
+ search: reactRouterLocation.search,
23384
+ hash: reactRouterLocation.hash
23385
+ }
23386
+ },
23387
+ children: children
23388
+ });
23389
+ }
23390
+ /**
23391
+ * Internal provider that uses window.location fallback
23392
+ * Used when not inside a React Router context
23393
+ */
23394
+ function FallbackNavigationProvider({
23395
+ children
23396
+ }) {
23397
+ const navigate = to => {
23398
+ if (typeof window === 'undefined') return;
23399
+ if (typeof to === 'string') {
23400
+ window.location.href = to;
23401
+ } else if (typeof to === 'number') {
23402
+ window.history.go(to);
23403
+ }
23404
+ };
23405
+ const location = typeof window !== 'undefined' ? {
23406
+ pathname: window.location.pathname,
23407
+ search: window.location.search,
23408
+ hash: window.location.hash
23409
+ } : undefined;
23410
+ return jsxRuntime.jsx(NavigationContext.Provider, {
23411
+ value: {
23412
+ navigate,
23413
+ location
23414
+ },
23415
+ children: children
23416
+ });
23417
+ }
23418
+ /**
23419
+ * Smart Navigation Provider
23420
+ *
23421
+ * Automatically detects if the app is inside a React Router context:
23422
+ * - If inside Router: uses React Router's useNavigate/useLocation (respects basename)
23423
+ * - If outside Router: falls back to window.location
23424
+ *
23425
+ * This is included automatically by QwickApp - you don't need to add it manually.
23426
+ */
23427
+ function NavigationProvider({
23428
+ children
23429
+ }) {
23430
+ // Check if we're inside a React Router by checking its internal context
23431
+ // useContext doesn't throw - it returns null if the context doesn't exist
23432
+ const routerContext = React.useContext(reactRouterDom.UNSAFE_NavigationContext);
23433
+ if (routerContext) {
23434
+ // We're inside a Router, use React Router's navigation
23435
+ return jsxRuntime.jsx(ReactRouterNavigationProvider, {
23436
+ children: children
23437
+ });
23438
+ }
23439
+ // Not inside a Router, use window.location fallback
23440
+ return jsxRuntime.jsx(FallbackNavigationProvider, {
23441
+ children: children
23442
+ });
23443
+ }
23444
+ /**
23445
+ * Hook to access navigation functions
23446
+ *
23447
+ * @returns Object containing navigate function and current location
23448
+ *
23449
+ * @example
23450
+ * ```tsx
23451
+ * function MyComponent() {
23452
+ * const { navigate, location } = useNavigation();
23453
+ *
23454
+ * const handleClick = () => {
23455
+ * navigate('/dashboard');
23456
+ * };
23457
+ *
23458
+ * return <button onClick={handleClick}>Go to Dashboard</button>;
23459
+ * }
23460
+ * ```
23461
+ */
23462
+ function useNavigation() {
23463
+ const context = React.useContext(NavigationContext);
23464
+ if (!context) {
23465
+ throw new Error('useNavigation must be used within a NavigationProvider. ' + 'Make sure your component is wrapped in QwickApp or NavigationProvider.');
23466
+ }
23467
+ return context;
23468
+ }
23469
+
23391
23470
  /**
23392
23471
  * Schema for PaletteSwitcher component - Color palette switching control
23393
23472
  *
@@ -24535,7 +24614,9 @@ const PageView = ({
24535
24614
  };
24536
24615
  }, [isPrintMode, printConfig]);
24537
24616
  // Route (fallback to current location)
24538
- const location = useSafeLocation();
24617
+ const {
24618
+ location
24619
+ } = useNavigation();
24539
24620
  const actualRoute = resolved.route || location?.pathname || '';
24540
24621
  // Context value
24541
24622
  const contextValue = React.useMemo(() => ({
@@ -24650,9 +24731,11 @@ const Scaffold = ({
24650
24731
  const [isDrawerOpen, setIsDrawerOpen] = React.useState(false);
24651
24732
  const [isRailExpanded, setIsRailExpanded] = React.useState(false);
24652
24733
  const [isMounted, setIsMounted] = React.useState(false);
24653
- // React Router hooks (if available)
24654
- const location = useSafeLocation();
24655
- const navigate = useSafeNavigate();
24734
+ // Navigation (uses React Router if available, falls back to window.location)
24735
+ const {
24736
+ navigate,
24737
+ location
24738
+ } = useNavigation();
24656
24739
  const currentPath = isMounted ? location?.pathname : undefined;
24657
24740
  // Debug logging for navigation
24658
24741
  React.useEffect(() => {
@@ -25021,9 +25104,11 @@ const ResponsiveMenu = props => {
25021
25104
  appName,
25022
25105
  logo: contextLogo
25023
25106
  } = useQwickApp$1();
25024
- // React Router hooks (if available)
25025
- const navigate = useSafeNavigate();
25026
- const location = useSafeLocation();
25107
+ // Navigation (uses React Router if available, falls back to window.location)
25108
+ const {
25109
+ navigate,
25110
+ location
25111
+ } = useNavigation();
25027
25112
  const currentPath = location?.pathname;
25028
25113
  // Debug logging
25029
25114
  React.useEffect(() => {
@@ -25925,17 +26010,19 @@ const QwickApp = ({
25925
26010
  }) : content;
25926
26011
  const appContent = jsxRuntime.jsx(ErrorBoundary, {
25927
26012
  children: jsxRuntime.jsx(AccessibilityProvider, {
25928
- children: jsxRuntime.jsx("div", {
25929
- className: `qwick-app ${className || ''}`,
25930
- style: style,
25931
- children: jsxRuntime.jsx(ThemeProvider, {
25932
- appId: resolvedConfig.appId,
25933
- defaultTheme: resolvedConfig.defaultTheme,
25934
- defaultPalette: resolvedConfig.defaultPalette,
25935
- children: jsxRuntime.jsx(QwickAppContext.Provider, {
25936
- value: contextValue,
25937
- children: jsxRuntime.jsx(PrintModeProvider, {
25938
- children: wrappedContent
26013
+ children: jsxRuntime.jsx(NavigationProvider, {
26014
+ children: jsxRuntime.jsx("div", {
26015
+ className: `qwick-app ${className || ''}`,
26016
+ style: style,
26017
+ children: jsxRuntime.jsx(ThemeProvider, {
26018
+ appId: resolvedConfig.appId,
26019
+ defaultTheme: resolvedConfig.defaultTheme,
26020
+ defaultPalette: resolvedConfig.defaultPalette,
26021
+ children: jsxRuntime.jsx(QwickAppContext.Provider, {
26022
+ value: contextValue,
26023
+ children: jsxRuntime.jsx(PrintModeProvider, {
26024
+ children: wrappedContent
26025
+ })
25939
26026
  })
25940
26027
  })
25941
26028
  })
@@ -31854,6 +31941,7 @@ exports.Image = Image;
31854
31941
  exports.Logo = Logo;
31855
31942
  exports.Markdown = Markdown;
31856
31943
  exports.ModelView = ModelView;
31944
+ exports.NavigationProvider = NavigationProvider;
31857
31945
  exports.Page = Page;
31858
31946
  exports.PageBannerHeader = PageBannerHeader;
31859
31947
  exports.PaletteAutumn = PaletteAutumn;
@@ -31954,14 +32042,13 @@ exports.useDataBinding = useDataBinding;
31954
32042
  exports.useDataContext = useDataContext;
31955
32043
  exports.useDataProvider = useDataProvider;
31956
32044
  exports.useDimensions = useDimensions;
32045
+ exports.useNavigation = useNavigation;
31957
32046
  exports.usePageContext = usePageContext;
31958
32047
  exports.usePalette = usePalette;
31959
32048
  exports.usePrintMode = usePrintMode$1;
31960
32049
  exports.usePrintModeHook = usePrintMode;
31961
32050
  exports.useQwickApp = useQwickApp;
31962
32051
  exports.useResolveTemplate = useResolveTemplate;
31963
- exports.useSafeLocation = useSafeLocation;
31964
- exports.useSafeNavigate = useSafeNavigate;
31965
32052
  exports.useTemplate = useTemplate;
31966
32053
  exports.useTheme = useTheme;
31967
32054
  exports.withAccessibility = withAccessibility;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "./manifest.schema.json",
3
- "version": "1.5.5",
3
+ "version": "1.5.6",
4
4
  "palettes": [
5
5
  {
6
6
  "id": "default",
@@ -8,11 +8,11 @@
8
8
  "description": "Classic blue and neutral color scheme - the original QwickApps palette",
9
9
  "author": "QwickApps",
10
10
  "license": "PolyForm-Shield-1.0.0",
11
- "version": "1.5.5",
12
- "file": "palette-default.1.5.5.css",
11
+ "version": "1.5.6",
12
+ "file": "palette-default.1.5.6.css",
13
13
  "primaryColor": "#007bff",
14
14
  "inlined": true,
15
- "fileMinified": "palette-default.1.5.5.min.css",
15
+ "fileMinified": "palette-default.1.5.6.min.css",
16
16
  "fileLatest": "palette-default.latest.css",
17
17
  "fileLatestMinified": "palette-default.latest.min.css"
18
18
  },
@@ -22,11 +22,11 @@
22
22
  "description": "Warm oranges, golden yellows, and earthy browns - inspired by fall foliage",
23
23
  "author": "QwickApps",
24
24
  "license": "PolyForm-Shield-1.0.0",
25
- "version": "1.5.5",
26
- "file": "palette-autumn.1.5.5.css",
25
+ "version": "1.5.6",
26
+ "file": "palette-autumn.1.5.6.css",
27
27
  "primaryColor": "#ea580c",
28
28
  "inlined": false,
29
- "fileMinified": "palette-autumn.1.5.5.min.css",
29
+ "fileMinified": "palette-autumn.1.5.6.min.css",
30
30
  "fileLatest": "palette-autumn.latest.css",
31
31
  "fileLatestMinified": "palette-autumn.latest.min.css"
32
32
  },
@@ -36,11 +36,11 @@
36
36
  "description": "Modern purple gradient for creative and tech brands - inspired by cosmic nebulae",
37
37
  "author": "QwickApps",
38
38
  "license": "PolyForm-Shield-1.0.0",
39
- "version": "1.5.5",
40
- "file": "palette-cosmic.1.5.5.css",
39
+ "version": "1.5.6",
40
+ "file": "palette-cosmic.1.5.6.css",
41
41
  "primaryColor": "#8b5cf6",
42
42
  "inlined": false,
43
- "fileMinified": "palette-cosmic.1.5.5.min.css",
43
+ "fileMinified": "palette-cosmic.1.5.6.min.css",
44
44
  "fileLatest": "palette-cosmic.latest.css",
45
45
  "fileLatestMinified": "palette-cosmic.latest.min.css"
46
46
  },
@@ -50,11 +50,11 @@
50
50
  "description": "Deep blues, aqua teals, and seafoam greens - inspired by ocean depths",
51
51
  "author": "QwickApps",
52
52
  "license": "PolyForm-Shield-1.0.0",
53
- "version": "1.5.5",
54
- "file": "palette-ocean.1.5.5.css",
53
+ "version": "1.5.6",
54
+ "file": "palette-ocean.1.5.6.css",
55
55
  "primaryColor": "#0891b2",
56
56
  "inlined": false,
57
- "fileMinified": "palette-ocean.1.5.5.min.css",
57
+ "fileMinified": "palette-ocean.1.5.6.min.css",
58
58
  "fileLatest": "palette-ocean.latest.css",
59
59
  "fileLatestMinified": "palette-ocean.latest.min.css"
60
60
  },
@@ -64,11 +64,11 @@
64
64
  "description": "Fresh greens, soft pinks, and bright yellows - inspired by spring blooms",
65
65
  "author": "QwickApps",
66
66
  "license": "PolyForm-Shield-1.0.0",
67
- "version": "1.5.5",
68
- "file": "palette-spring.1.5.5.css",
67
+ "version": "1.5.6",
68
+ "file": "palette-spring.1.5.6.css",
69
69
  "primaryColor": "#16a34a",
70
70
  "inlined": false,
71
- "fileMinified": "palette-spring.1.5.5.min.css",
71
+ "fileMinified": "palette-spring.1.5.6.min.css",
72
72
  "fileLatest": "palette-spring.latest.css",
73
73
  "fileLatestMinified": "palette-spring.latest.min.css"
74
74
  },
@@ -78,11 +78,11 @@
78
78
  "description": "Cool blues, icy whites, and frosty grays - inspired by winter landscapes",
79
79
  "author": "QwickApps",
80
80
  "license": "PolyForm-Shield-1.0.0",
81
- "version": "1.5.5",
82
- "file": "palette-winter.1.5.5.css",
81
+ "version": "1.5.6",
82
+ "file": "palette-winter.1.5.6.css",
83
83
  "primaryColor": "#0077be",
84
84
  "inlined": false,
85
- "fileMinified": "palette-winter.1.5.5.min.css",
85
+ "fileMinified": "palette-winter.1.5.6.min.css",
86
86
  "fileLatest": "palette-winter.latest.css",
87
87
  "fileLatestMinified": "palette-winter.latest.min.css"
88
88
  }
@@ -1 +1 @@
1
- {"version":3,"file":"iconMap.d.ts","sourceRoot":"","sources":["../../src/utils/iconMap.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAsE1B;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC;CAChC;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAoG/C,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,GAAE,MAAa,GAAG,MAAM,CAI1F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAWxF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAErE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C"}
1
+ {"version":3,"file":"iconMap.d.ts","sourceRoot":"","sources":["../../src/utils/iconMap.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAuE1B;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC;CAChC;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAqG/C,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,GAAE,MAAa,GAAG,MAAM,CAI1F;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAWxF;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAErE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAE7C"}
@@ -5,28 +5,6 @@
5
5
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
6
6
  */
7
7
  import { ReactNode } from 'react';
8
- /** Location type for routing */
9
- type LocationType = {
10
- pathname: string;
11
- search: string;
12
- hash: string;
13
- };
14
- /**
15
- * Get the current location from browser or undefined in SSR
16
- * Works without relying on routing libraries
17
- * @returns {object | undefined} - The location object if in browser, otherwise undefined
18
- */
19
- export declare const useSafeLocation: () => LocationType | undefined;
20
- /**
21
- * Navigate function type
22
- */
23
- export type NavigateFunction = (to: string | number, options?: unknown) => void;
24
- /**
25
- * Get a navigation function with fallback to window.location
26
- * Works without relying on routing libraries
27
- * @returns {NavigateFunction} - The navigate function
28
- */
29
- export declare const useSafeNavigate: () => NavigateFunction;
30
8
  /**
31
9
  * Extract text content from ReactNode for code processing
32
10
  * Handles natural React usage like <Code>const x = 1;</Code>
@@ -35,5 +13,4 @@ export declare const useSafeNavigate: () => NavigateFunction;
35
13
  * @returns String representation of the node's text content
36
14
  */
37
15
  export declare function extractTextFromReactNode(node: ReactNode): string;
38
- export {};
39
16
  //# sourceMappingURL=reactUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reactUtils.d.ts","sourceRoot":"","sources":["../../src/utils/reactUtils.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,gCAAgC;AAChC,KAAK,YAAY,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAO,YAAY,GAAG,SAUjD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAEhF;;;;GAIG;AACH,eAAO,MAAM,eAAe,QAAO,gBAalC,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CA2BhE"}
1
+ {"version":3,"file":"reactUtils.d.ts","sourceRoot":"","sources":["../../src/utils/reactUtils.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CA2BhE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qwickapps/react-framework",
3
- "version": "1.5.5",
3
+ "version": "1.5.6",
4
4
  "type": "module",
5
5
  "description": "Complete React framework with responsive navigation, flexible layouts, theming system, and reusable components for building modern applications.",
6
6
  "main": "dist/index.js",
@@ -35,7 +35,7 @@
35
35
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
36
36
  */
37
37
  import React, { cloneElement, useState } from 'react';
38
- import { DataProvider, ThemeProvider, PrintModeProvider, type ThemeMode } from '../contexts';
38
+ import { DataProvider, ThemeProvider, PrintModeProvider, NavigationProvider, type ThemeMode } from '../contexts';
39
39
  import { QwickAppContext, type QwickAppContextValue, type QwickAppProps } from '../contexts/QwickAppContext';
40
40
  import { type TemplateResolverConfig } from '../types';
41
41
  import { AppConfig } from '../config';
@@ -160,19 +160,21 @@ export const QwickApp: React.FC<QwickAppComponentProps> = ({
160
160
  const appContent = (
161
161
  <ErrorBoundary>
162
162
  <AccessibilityProvider>
163
- <div className={`qwick-app ${className || ''}`} style={style}>
164
- <ThemeProvider
165
- appId={resolvedConfig.appId}
166
- defaultTheme={resolvedConfig.defaultTheme}
167
- defaultPalette={resolvedConfig.defaultPalette}
168
- >
169
- <QwickAppContext.Provider value={contextValue}>
170
- <PrintModeProvider>
171
- {wrappedContent}
172
- </PrintModeProvider>
173
- </QwickAppContext.Provider>
174
- </ThemeProvider>
175
- </div>
163
+ <NavigationProvider>
164
+ <div className={`qwick-app ${className || ''}`} style={style}>
165
+ <ThemeProvider
166
+ appId={resolvedConfig.appId}
167
+ defaultTheme={resolvedConfig.defaultTheme}
168
+ defaultPalette={resolvedConfig.defaultPalette}
169
+ >
170
+ <QwickAppContext.Provider value={contextValue}>
171
+ <PrintModeProvider>
172
+ {wrappedContent}
173
+ </PrintModeProvider>
174
+ </QwickAppContext.Provider>
175
+ </ThemeProvider>
176
+ </div>
177
+ </NavigationProvider>
176
178
  </AccessibilityProvider>
177
179
  </ErrorBoundary>
178
180
  );
@@ -22,7 +22,7 @@ import { useQwickApp } from '../contexts/QwickAppContext';
22
22
  import Logo from './Logo';
23
23
  import { getIconComponent } from './buttons/Button';
24
24
  import './ResponsiveMenu.css';
25
- import { useSafeLocation, useSafeNavigate } from '../utils/reactUtils';
25
+ import { useNavigation } from '../contexts/NavigationContext';
26
26
  import { loggers } from '../utils/logger';
27
27
  import type { MenuItem } from './menu/MenuItem';
28
28
 
@@ -63,9 +63,8 @@ const ResponsiveMenu: React.FC<ResponsiveMenuProps> = (props) => {
63
63
  const [isDrawerOpen, setIsDrawerOpen] = useState(false);
64
64
  const { appName, logo: contextLogo } = useQwickApp();
65
65
 
66
- // React Router hooks (if available)
67
- const navigate = useSafeNavigate();
68
- const location = useSafeLocation();
66
+ // Navigation (uses React Router if available, falls back to window.location)
67
+ const { navigate, location } = useNavigation();
69
68
  const currentPath = location?.pathname;
70
69
 
71
70
  // Debug logging
@@ -24,7 +24,7 @@ import PaletteSwitcher from './buttons/PaletteSwitcher';
24
24
  import { RadioButtonUnchecked as DefaultIcon } from '@mui/icons-material';
25
25
  import { getIconComponent } from './buttons/Button';
26
26
  import './Scaffold.css';
27
- import { useSafeLocation, useSafeNavigate } from '../utils/reactUtils';
27
+ import { useNavigation } from '../contexts/NavigationContext';
28
28
  import { loggers } from '../utils/logger';
29
29
  import type { MenuItem } from './menu/MenuItem';
30
30
 
@@ -92,9 +92,8 @@ const Scaffold: React.FC<ScaffoldProps> = ({
92
92
  const [isRailExpanded, setIsRailExpanded] = useState(false);
93
93
  const [isMounted, setIsMounted] = useState(false);
94
94
 
95
- // React Router hooks (if available)
96
- const location = useSafeLocation();
97
- const navigate = useSafeNavigate();
95
+ // Navigation (uses React Router if available, falls back to window.location)
96
+ const { navigate, location } = useNavigation();
98
97
  const currentPath = isMounted ? location?.pathname : undefined;
99
98
 
100
99
  // Debug logging for navigation
@@ -25,6 +25,7 @@ export * from './layout';
25
25
  export * from './pages';
26
26
  export { default as Scaffold } from './Scaffold';
27
27
  export type { ScaffoldProps, AppBarProps } from './Scaffold';
28
+ export type { MenuItem } from './menu/MenuItem';
28
29
  export { default as ResponsiveMenu } from './ResponsiveMenu';
29
30
  export type { ResponsiveMenuProps } from './ResponsiveMenu';
30
31
  export * from './QwickApp';
@@ -38,7 +38,7 @@ import { usePrintMode } from '../../hooks/usePrintMode';
38
38
  import { PageTemplateSchema } from '../../schemas/PageTemplateSchema';
39
39
  import { PrintConfigSchema } from '../../schemas/PrintConfigSchema';
40
40
  import { toCssLength } from '../../utils/cssUtils';
41
- import { useSafeLocation } from '../../utils/reactUtils';
41
+ import { useNavigation } from '../../contexts/NavigationContext';
42
42
  import { SafeSpan } from '../SafeSpan';
43
43
  import './Page.css';
44
44
  import { Box } from '@mui/material';
@@ -275,7 +275,7 @@ export const PageView: React.FC<PageViewProps> = ({
275
275
  }, [isPrintMode, printConfig]);
276
276
 
277
277
  // Route (fallback to current location)
278
- const location = useSafeLocation();
278
+ const { location } = useNavigation();
279
279
  const actualRoute = resolved.route || location?.pathname || '';
280
280
 
281
281
  // Context value
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Navigation Context - Smart navigation that auto-detects React Router
3
+ *
4
+ * Provides navigation functions that work with React Router when available,
5
+ * falling back to window.location for non-router apps or SSR.
6
+ *
7
+ * Usage:
8
+ * - Wrap your app with NavigationProvider (done automatically by QwickApp)
9
+ * - Use useNavigation() hook to get navigate function and location
10
+ *
11
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
12
+ */
13
+
14
+ import { createContext, useContext, type ReactNode } from 'react';
15
+ import {
16
+ useNavigate,
17
+ useLocation,
18
+ UNSAFE_NavigationContext as RouterContext,
19
+ } from 'react-router-dom';
20
+
21
+ /**
22
+ * Location type matching React Router's location shape
23
+ */
24
+ export interface NavigationLocation {
25
+ pathname: string;
26
+ search: string;
27
+ hash: string;
28
+ }
29
+
30
+ /**
31
+ * Navigate function type
32
+ */
33
+ export type NavigateFunction = (to: string | number) => void;
34
+
35
+ /**
36
+ * Navigation context value
37
+ */
38
+ export interface NavigationContextValue {
39
+ navigate: NavigateFunction;
40
+ location: NavigationLocation | undefined;
41
+ }
42
+
43
+ const NavigationContext = createContext<NavigationContextValue | null>(null);
44
+
45
+ /**
46
+ * Internal provider that uses React Router hooks
47
+ * Only rendered when we're inside a Router context
48
+ */
49
+ function ReactRouterNavigationProvider({ children }: { children: ReactNode }) {
50
+ const reactRouterNavigate = useNavigate();
51
+ const reactRouterLocation = useLocation();
52
+
53
+ const navigate: NavigateFunction = (to) => {
54
+ if (typeof to === 'string') {
55
+ reactRouterNavigate(to);
56
+ } else if (typeof to === 'number') {
57
+ reactRouterNavigate(to);
58
+ }
59
+ };
60
+
61
+ return (
62
+ <NavigationContext.Provider
63
+ value={{
64
+ navigate,
65
+ location: {
66
+ pathname: reactRouterLocation.pathname,
67
+ search: reactRouterLocation.search,
68
+ hash: reactRouterLocation.hash,
69
+ },
70
+ }}
71
+ >
72
+ {children}
73
+ </NavigationContext.Provider>
74
+ );
75
+ }
76
+
77
+ /**
78
+ * Internal provider that uses window.location fallback
79
+ * Used when not inside a React Router context
80
+ */
81
+ function FallbackNavigationProvider({ children }: { children: ReactNode }) {
82
+ const navigate: NavigateFunction = (to) => {
83
+ if (typeof window === 'undefined') return;
84
+
85
+ if (typeof to === 'string') {
86
+ window.location.href = to;
87
+ } else if (typeof to === 'number') {
88
+ window.history.go(to);
89
+ }
90
+ };
91
+
92
+ const location: NavigationLocation | undefined =
93
+ typeof window !== 'undefined'
94
+ ? {
95
+ pathname: window.location.pathname,
96
+ search: window.location.search,
97
+ hash: window.location.hash,
98
+ }
99
+ : undefined;
100
+
101
+ return (
102
+ <NavigationContext.Provider value={{ navigate, location }}>
103
+ {children}
104
+ </NavigationContext.Provider>
105
+ );
106
+ }
107
+
108
+ /**
109
+ * Smart Navigation Provider
110
+ *
111
+ * Automatically detects if the app is inside a React Router context:
112
+ * - If inside Router: uses React Router's useNavigate/useLocation (respects basename)
113
+ * - If outside Router: falls back to window.location
114
+ *
115
+ * This is included automatically by QwickApp - you don't need to add it manually.
116
+ */
117
+ export function NavigationProvider({ children }: { children: ReactNode }) {
118
+ // Check if we're inside a React Router by checking its internal context
119
+ // useContext doesn't throw - it returns null if the context doesn't exist
120
+ const routerContext = useContext(RouterContext);
121
+
122
+ if (routerContext) {
123
+ // We're inside a Router, use React Router's navigation
124
+ return (
125
+ <ReactRouterNavigationProvider>{children}</ReactRouterNavigationProvider>
126
+ );
127
+ }
128
+
129
+ // Not inside a Router, use window.location fallback
130
+ return <FallbackNavigationProvider>{children}</FallbackNavigationProvider>;
131
+ }
132
+
133
+ /**
134
+ * Hook to access navigation functions
135
+ *
136
+ * @returns Object containing navigate function and current location
137
+ *
138
+ * @example
139
+ * ```tsx
140
+ * function MyComponent() {
141
+ * const { navigate, location } = useNavigation();
142
+ *
143
+ * const handleClick = () => {
144
+ * navigate('/dashboard');
145
+ * };
146
+ *
147
+ * return <button onClick={handleClick}>Go to Dashboard</button>;
148
+ * }
149
+ * ```
150
+ */
151
+ export function useNavigation(): NavigationContextValue {
152
+ const context = useContext(NavigationContext);
153
+
154
+ if (!context) {
155
+ throw new Error(
156
+ 'useNavigation must be used within a NavigationProvider. ' +
157
+ 'Make sure your component is wrapped in QwickApp or NavigationProvider.'
158
+ );
159
+ }
160
+
161
+ return context;
162
+ }
@@ -3,6 +3,8 @@ export { DataProvider, t, T, useData, useDataContext, useDataProvider, useResolv
3
3
  export type { DataProviderProps } from './DataContext';
4
4
  export { DimensionsProvider, useDimensions } from './DimensionsContext';
5
5
  export type { DimensionsContextValue, DimensionTokens } from './DimensionsContext';
6
+ export { NavigationProvider, useNavigation } from './NavigationContext';
7
+ export type { NavigateFunction, NavigationContextValue, NavigationLocation } from './NavigationContext';
6
8
  export { PaletteProvider, usePalette } from './PaletteContext';
7
9
  export type { PaletteConfig, PaletteContextValue } from './PaletteContext';
8
10
  export { ThemeProvider, useTheme } from './ThemeContext';
@@ -75,6 +75,7 @@ import {
75
75
  CheckCircle,
76
76
  RotateRight,
77
77
  Memory,
78
+ LocalOffer,
78
79
  } from '@mui/icons-material';
79
80
 
80
81
  /**
@@ -189,6 +190,7 @@ export const iconMap: Record<string, IconMapping> = {
189
190
  check_circle: { emoji: '✅', component: CheckCircle },
190
191
  rotate_right: { emoji: '🔄', component: RotateRight },
191
192
  memory: { emoji: '🧠', component: Memory },
193
+ local_offer: { emoji: '🏷️', component: LocalOffer },
192
194
  };
193
195
 
194
196
  /**
@@ -7,55 +7,10 @@
7
7
 
8
8
  import { ReactNode } from 'react';
9
9
 
10
- /** Location type for routing */
11
- type LocationType = { pathname: string, search: string, hash: string };
12
-
13
- /**
14
- * Get the current location from browser or undefined in SSR
15
- * Works without relying on routing libraries
16
- * @returns {object | undefined} - The location object if in browser, otherwise undefined
17
- */
18
- export const useSafeLocation = (): LocationType | undefined => {
19
- // Use browser location if available (works in any React app)
20
- if (typeof window !== 'undefined') {
21
- return {
22
- pathname: window.location.pathname,
23
- search: window.location.search,
24
- hash: window.location.hash
25
- };
26
- }
27
- return undefined;
28
- };
29
-
30
- /**
31
- * Navigate function type
32
- */
33
- export type NavigateFunction = (to: string | number, options?: unknown) => void;
34
-
35
- /**
36
- * Get a navigation function with fallback to window.location
37
- * Works without relying on routing libraries
38
- * @returns {NavigateFunction} - The navigate function
39
- */
40
- export const useSafeNavigate = (): NavigateFunction => {
41
- // Return function that uses window.location
42
- return (to: string | number) => {
43
- if (typeof to === 'string') {
44
- if (typeof window !== 'undefined') {
45
- window.location.href = to;
46
- }
47
- } else if (typeof to === 'number') {
48
- if (typeof window !== 'undefined' && window.history) {
49
- window.history.go(to);
50
- }
51
- }
52
- };
53
- };
54
-
55
10
  /**
56
11
  * Extract text content from ReactNode for code processing
57
12
  * Handles natural React usage like <Code>const x = 1;</Code>
58
- *
13
+ *
59
14
  * @param node - The ReactNode to extract text from
60
15
  * @returns String representation of the node's text content
61
16
  */
@@ -73,7 +28,7 @@ export function extractTextFromReactNode(node: ReactNode): string {
73
28
  }
74
29
 
75
30
  if (Array.isArray(node)) {
76
- return node.map(child => extractTextFromReactNode(child)).join('');
31
+ return node.map((child) => extractTextFromReactNode(child)).join('');
77
32
  }
78
33
 
79
34
  // For React elements, try to extract text content