piral-breadcrumbs 1.1.0-beta.5752 → 1.1.0-beta.5772

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.
@@ -3,6 +3,12 @@ import * as React from 'react';
3
3
  import { useLocation, useRouteMatch } from 'react-router';
4
4
  import { PiralBreadcrumbsContainer, PiralBreadcrumbItem } from './components';
5
5
  import { useBreadcrumbs } from './useBreadcrumbs';
6
+ function getContent(title, location, path, params) {
7
+ if (typeof title === 'function') {
8
+ return title({ location, path, params });
9
+ }
10
+ return title;
11
+ }
6
12
  export const Breadcrumbs = () => {
7
13
  var _a;
8
14
  const location = useLocation();
@@ -14,8 +20,13 @@ export const Breadcrumbs = () => {
14
20
  const { title, path } = settings, props = __rest(settings, ["title", "path"]);
15
21
  const key = `bc_${i}_${settings.path}`;
16
22
  const current = i === currentIndex;
17
- const computedPath = path.replace(/:([A-Za-z0-9_]+)/g, (s, id) => { var _a; return (_a = params[id]) !== null && _a !== void 0 ? _a : s; });
18
- return (React.createElement(PiralBreadcrumbItem, Object.assign({ key: key, current: current, path: computedPath }, props), title));
23
+ const computedPath = path.replace(/:(([A-Za-z0-9_]+)\*?)/g, (s, _, id) => {
24
+ if (id in params) {
25
+ return params[id] || '';
26
+ }
27
+ return s;
28
+ });
29
+ return (React.createElement(PiralBreadcrumbItem, Object.assign({ key: key, current: current, path: computedPath }, props), getContent(title, location, computedPath, params)));
19
30
  });
20
31
  return React.createElement(PiralBreadcrumbsContainer, { children: children });
21
32
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../src/Breadcrumbs.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,CAAC,MAAM,WAAW,GAAa,GAAG,EAAE;;IACxC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAC,IAAI,mCAAI,GAAG,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE;QACnD,MAAM,EAAE,KAAK,EAAE,IAAI,KAAe,QAAQ,EAAlB,KAAK,UAAK,QAAQ,EAApC,iBAAyB,CAAW,CAAC;QAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,CAAC,KAAK,YAAY,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,WAAC,OAAA,MAAA,MAAM,CAAC,EAAE,CAAC,mCAAI,CAAC,CAAA,EAAA,CAAC,CAAC;QAEnF,OAAO,CACL,oBAAC,mBAAmB,kBAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,IAAM,KAAK,GAC3E,KAAK,CACc,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,oBAAC,yBAAyB,IAAC,QAAQ,EAAE,QAAQ,GAAI,CAAC;AAC3D,CAAC,CAAC;AACF,WAAW,CAAC,WAAW,GAAG,aAAa,CAAC"}
1
+ {"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../src/Breadcrumbs.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIlD,SAAS,UAAU,CACjB,KAAkC,EAClC,QAAkB,EAClB,IAAY,EACZ,MAA8B;IAE9B,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE;QAC/B,OAAO,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;KAC1C;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAa,GAAG,EAAE;;IACxC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAC,IAAI,mCAAI,GAAG,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE;QACnD,MAAM,EAAE,KAAK,EAAE,IAAI,KAAe,QAAQ,EAAlB,KAAK,UAAK,QAAQ,EAApC,iBAAyB,CAAW,CAAC;QAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,CAAC,KAAK,YAAY,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE;YACvE,IAAI,EAAE,IAAI,MAAM,EAAE;gBAChB,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;aACzB;YAED,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,OAAO,CACL,oBAAC,mBAAmB,kBAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,IAAM,KAAK,GAC3E,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,CAC9B,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,oBAAC,yBAAyB,IAAC,QAAQ,EAAE,QAAQ,GAAI,CAAC;AAC3D,CAAC,CAAC;AACF,WAAW,CAAC,WAAW,GAAG,aAAa,CAAC"}
package/esm/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ComponentType, ReactNode } from 'react';
2
2
  import type { Dict, BaseRegistration, RegistrationDisposer } from 'piral-core';
3
+ import type { Location } from 'history';
3
4
  declare module 'piral-core/lib/types/custom' {
4
5
  interface PiletCustomApi extends PiletBreadcrumbsApi {
5
6
  }
@@ -52,6 +53,11 @@ export interface BreadcrumbItemProps extends Omit<BreadcrumbSettings, 'title'> {
52
53
  }
53
54
  export interface PiralCustomBreadcrumbSettings {
54
55
  }
56
+ export interface BreadcrumbTitleParams {
57
+ location: Location;
58
+ path: string;
59
+ params: Record<string, string>;
60
+ }
55
61
  export interface BreadcrumbSettings extends PiralCustomBreadcrumbSettings {
56
62
  /**
57
63
  * Gets the path of breadcrumb for navigation purposes.
@@ -77,7 +83,7 @@ export interface BreadcrumbSettings extends PiralCustomBreadcrumbSettings {
77
83
  /**
78
84
  * The title of the breadcrumb.
79
85
  */
80
- title: ReactNode;
86
+ title: ReactNode | ((params: BreadcrumbTitleParams) => ReactNode);
81
87
  }
82
88
  export interface BreadcrumbRegistration extends BaseRegistration {
83
89
  matcher: RegExp;
@@ -6,6 +6,12 @@ const React = require("react");
6
6
  const react_router_1 = require("react-router");
7
7
  const components_1 = require("./components");
8
8
  const useBreadcrumbs_1 = require("./useBreadcrumbs");
9
+ function getContent(title, location, path, params) {
10
+ if (typeof title === 'function') {
11
+ return title({ location, path, params });
12
+ }
13
+ return title;
14
+ }
9
15
  const Breadcrumbs = () => {
10
16
  var _a;
11
17
  const location = (0, react_router_1.useLocation)();
@@ -17,8 +23,13 @@ const Breadcrumbs = () => {
17
23
  const { title, path } = settings, props = tslib_1.__rest(settings, ["title", "path"]);
18
24
  const key = `bc_${i}_${settings.path}`;
19
25
  const current = i === currentIndex;
20
- const computedPath = path.replace(/:([A-Za-z0-9_]+)/g, (s, id) => { var _a; return (_a = params[id]) !== null && _a !== void 0 ? _a : s; });
21
- return (React.createElement(components_1.PiralBreadcrumbItem, Object.assign({ key: key, current: current, path: computedPath }, props), title));
26
+ const computedPath = path.replace(/:(([A-Za-z0-9_]+)\*?)/g, (s, _, id) => {
27
+ if (id in params) {
28
+ return params[id] || '';
29
+ }
30
+ return s;
31
+ });
32
+ return (React.createElement(components_1.PiralBreadcrumbItem, Object.assign({ key: key, current: current, path: computedPath }, props), getContent(title, location, computedPath, params)));
22
33
  });
23
34
  return React.createElement(components_1.PiralBreadcrumbsContainer, { children: children });
24
35
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../src/Breadcrumbs.tsx"],"names":[],"mappings":";;;;AAAA,+BAA+B;AAC/B,+CAA0D;AAC1D,6CAA8E;AAC9E,qDAAkD;AAE3C,MAAM,WAAW,GAAa,GAAG,EAAE;;IACxC,MAAM,QAAQ,GAAG,IAAA,0BAAW,GAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,IAAA,+BAAc,EAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,4BAAa,EAAC,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAC,IAAI,mCAAI,GAAG,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE;QACnD,MAAM,EAAE,KAAK,EAAE,IAAI,KAAe,QAAQ,EAAlB,KAAK,kBAAK,QAAQ,EAApC,iBAAyB,CAAW,CAAC;QAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,CAAC,KAAK,YAAY,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,WAAC,OAAA,MAAA,MAAM,CAAC,EAAE,CAAC,mCAAI,CAAC,CAAA,EAAA,CAAC,CAAC;QAEnF,OAAO,CACL,oBAAC,gCAAmB,kBAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,IAAM,KAAK,GAC3E,KAAK,CACc,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,oBAAC,sCAAyB,IAAC,QAAQ,EAAE,QAAQ,GAAI,CAAC;AAC3D,CAAC,CAAC;AArBW,QAAA,WAAW,eAqBtB;AACF,mBAAW,CAAC,WAAW,GAAG,aAAa,CAAC"}
1
+ {"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../src/Breadcrumbs.tsx"],"names":[],"mappings":";;;;AAAA,+BAA+B;AAC/B,+CAA0D;AAC1D,6CAA8E;AAC9E,qDAAkD;AAIlD,SAAS,UAAU,CACjB,KAAkC,EAClC,QAAkB,EAClB,IAAY,EACZ,MAA8B;IAE9B,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE;QAC/B,OAAO,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;KAC1C;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAEM,MAAM,WAAW,GAAa,GAAG,EAAE;;IACxC,MAAM,QAAQ,GAAG,IAAA,0BAAW,GAAE,CAAC;IAC/B,MAAM,WAAW,GAAG,IAAA,+BAAc,EAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IAC1C,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,4BAAa,EAAC,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,CAAC,IAAI,mCAAI,GAAG,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE;QACnD,MAAM,EAAE,KAAK,EAAE,IAAI,KAAe,QAAQ,EAAlB,KAAK,kBAAK,QAAQ,EAApC,iBAAyB,CAAW,CAAC;QAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,CAAC,KAAK,YAAY,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE;YACvE,IAAI,EAAE,IAAI,MAAM,EAAE;gBAChB,OAAO,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;aACzB;YAED,OAAO,CAAC,CAAC;QACX,CAAC,CAAC,CAAC;QAEH,OAAO,CACL,oBAAC,gCAAmB,kBAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,IAAM,KAAK,GAC3E,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,CAC9B,CACvB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,oBAAC,sCAAyB,IAAC,QAAQ,EAAE,QAAQ,GAAI,CAAC;AAC3D,CAAC,CAAC;AA3BW,QAAA,WAAW,eA2BtB;AACF,mBAAW,CAAC,WAAW,GAAG,aAAa,CAAC"}
package/lib/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ComponentType, ReactNode } from 'react';
2
2
  import type { Dict, BaseRegistration, RegistrationDisposer } from 'piral-core';
3
+ import type { Location } from 'history';
3
4
  declare module 'piral-core/lib/types/custom' {
4
5
  interface PiletCustomApi extends PiletBreadcrumbsApi {
5
6
  }
@@ -52,6 +53,11 @@ export interface BreadcrumbItemProps extends Omit<BreadcrumbSettings, 'title'> {
52
53
  }
53
54
  export interface PiralCustomBreadcrumbSettings {
54
55
  }
56
+ export interface BreadcrumbTitleParams {
57
+ location: Location;
58
+ path: string;
59
+ params: Record<string, string>;
60
+ }
55
61
  export interface BreadcrumbSettings extends PiralCustomBreadcrumbSettings {
56
62
  /**
57
63
  * Gets the path of breadcrumb for navigation purposes.
@@ -77,7 +83,7 @@ export interface BreadcrumbSettings extends PiralCustomBreadcrumbSettings {
77
83
  /**
78
84
  * The title of the breadcrumb.
79
85
  */
80
- title: ReactNode;
86
+ title: ReactNode | ((params: BreadcrumbTitleParams) => ReactNode);
81
87
  }
82
88
  export interface BreadcrumbRegistration extends BaseRegistration {
83
89
  matcher: RegExp;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "piral-breadcrumbs",
3
- "version": "1.1.0-beta.5752",
3
+ "version": "1.1.0-beta.5772",
4
4
  "description": "Plugin for creating a breadcrumb manager in Piral.",
5
5
  "keywords": [
6
6
  "piral",
@@ -66,9 +66,9 @@
66
66
  "devDependencies": {
67
67
  "@types/react": "^18.0.0",
68
68
  "@types/react-router": "^5.1.8",
69
- "piral-core": "1.1.0-beta.5752",
69
+ "piral-core": "1.1.0-beta.5772",
70
70
  "react": "^18.0.0",
71
71
  "react-router": "^5.2.0"
72
72
  },
73
- "gitHead": "a25a97f00b21282f33439320bef90ccbcc27ee96"
73
+ "gitHead": "d8e1c4bdf3a7ebb171fd3b05fdbe2f9fd97f259f"
74
74
  }
@@ -1 +1 @@
1
- (()=>{var pr=Object.create;var C=Object.defineProperty,lr=Object.defineProperties,dr=Object.getOwnPropertyDescriptor,fr=Object.getOwnPropertyDescriptors,br=Object.getOwnPropertyNames,S=Object.getOwnPropertySymbols,gr=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty,z=Object.prototype.propertyIsEnumerable;var H=(r,e,t)=>e in r?C(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,f=(r,e)=>{for(var t in e||(e={}))G.call(e,t)&&H(r,t,e[t]);if(S)for(var t of S(e))z.call(e,t)&&H(r,t,e[t]);return r},g=(r,e)=>lr(r,fr(e)),K=r=>C(r,"__esModule",{value:!0});var B=(r=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(r,{get:(e,t)=>(typeof require!="undefined"?require:e)[t]}):r)(function(r){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+r+'" is not supported')}),L=r=>typeof r=="symbol"?r:r+"",y=(r,e)=>{var t={};for(var a in r)G.call(r,a)&&e.indexOf(a)<0&&(t[a]=r[a]);if(r!=null&&S)for(var a of S(r))e.indexOf(a)<0&&z.call(r,a)&&(t[a]=r[a]);return t};var W=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),hr=(r,e)=>{K(r);for(var t in e)C(r,t,{get:e[t],enumerable:!0})},Br=(r,e,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of br(e))!G.call(r,a)&&a!=="default"&&C(r,a,{get:()=>e[a],enumerable:!(t=dr(e,a))||t.enumerable});return r},x=r=>Br(K(C(r!=null?pr(gr(r)):{},"default",r&&r.__esModule&&"default"in r?{get:()=>r.default,enumerable:!0}:{value:r,enumerable:!0})),r);var tr=W((qr,er)=>{er.exports=Array.isArray||function(r){return Object.prototype.toString.call(r)=="[object Array]"}});var cr=W((Jr,R)=>{var D=tr();R.exports=ir;R.exports.parse=N;R.exports.compile=Er;R.exports.tokensToFunction=ar;R.exports.tokensToRegExp=nr;var Cr=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function N(r,e){for(var t=[],a=0,o=0,i="",m=e&&e.delimiter||"/",n;(n=Cr.exec(r))!=null;){var s=n[0],u=n[1],p=n.index;if(i+=r.slice(o,p),o=p+s.length,u){i+=u[1];continue}var c=r[o],l=n[2],d=n[3],b=n[4],w=n[5],v=n[6],P=n[7];i&&(t.push(i),i="");var A=l!=null&&c!=null&&c!==l,sr=v==="+"||v==="*",mr=v==="?"||v==="*",J=n[2]||m,M=b||w;t.push({name:d||a++,prefix:l||"",delimiter:J,optional:mr,repeat:sr,partial:A,asterisk:!!P,pattern:M?Ar(M):P?".*":"[^"+$(J)+"]+?"})}return o<r.length&&(i+=r.substr(o)),i&&t.push(i),t}function Er(r,e){return ar(N(r,e),e)}function wr(r){return encodeURI(r).replace(/[\/?#]/g,function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})}function Pr(r){return encodeURI(r).replace(/[?#]/g,function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})}function ar(r,e){for(var t=new Array(r.length),a=0;a<r.length;a++)typeof r[a]=="object"&&(t[a]=new RegExp("^(?:"+r[a].pattern+")$",q(e)));return function(o,i){for(var m="",n=o||{},s=i||{},u=s.pretty?wr:encodeURIComponent,p=0;p<r.length;p++){var c=r[p];if(typeof c=="string"){m+=c;continue}var l=n[c.name],d;if(l==null)if(c.optional){c.partial&&(m+=c.prefix);continue}else throw new TypeError('Expected "'+c.name+'" to be defined');if(D(l)){if(!c.repeat)throw new TypeError('Expected "'+c.name+'" to not repeat, but received `'+JSON.stringify(l)+"`");if(l.length===0){if(c.optional)continue;throw new TypeError('Expected "'+c.name+'" to not be empty')}for(var b=0;b<l.length;b++){if(d=u(l[b]),!t[p].test(d))throw new TypeError('Expected all "'+c.name+'" to match "'+c.pattern+'", but received `'+JSON.stringify(d)+"`");m+=(b===0?c.prefix:c.delimiter)+d}continue}if(d=c.asterisk?Pr(l):u(l),!t[p].test(d))throw new TypeError('Expected "'+c.name+'" to match "'+c.pattern+'", but received "'+d+'"');m+=c.prefix+d}return m}}function $(r){return r.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function Ar(r){return r.replace(/([=!:$\/()])/g,"\\$1")}function O(r,e){return r.keys=e,r}function q(r){return r&&r.sensitive?"":"i"}function Sr(r,e){var t=r.source.match(/\((?!\?)/g);if(t)for(var a=0;a<t.length;a++)e.push({name:a,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return O(r,e)}function Ir(r,e,t){for(var a=[],o=0;o<r.length;o++)a.push(ir(r[o],e,t).source);var i=new RegExp("(?:"+a.join("|")+")",q(t));return O(i,e)}function Tr(r,e,t){return nr(N(r,t),e,t)}function nr(r,e,t){D(e)||(t=e||t,e=[]),t=t||{};for(var a=t.strict,o=t.end!==!1,i="",m=0;m<r.length;m++){var n=r[m];if(typeof n=="string")i+=$(n);else{var s=$(n.prefix),u="(?:"+n.pattern+")";e.push(n),n.repeat&&(u+="(?:"+s+u+")*"),n.optional?n.partial?u=s+"("+u+")?":u="(?:"+s+"("+u+"))?":u=s+"("+u+")",i+=u}}var p=$(t.delimiter||"/"),c=i.slice(-p.length)===p;return a||(i=(c?i.slice(0,-p.length):i)+"(?:"+p+"(?=$))?"),o?i+="$":i+=a&&c?"":"(?="+p+"|$)",O(new RegExp("^"+i,q(t)),e)}function ir(r,e,t){return D(e)||(t=e||t,e=[]),t=t||{},r instanceof RegExp?Sr(r,e):D(r)?Ir(r,e,t):Tr(r,e,t)}});var U=x(B("react")),T=x(B("react-router"));var _=x(B("piral-core")),X=(0,_.getPiralComponent)("BreadcrumbsContainer"),Z=(0,_.getPiralComponent)("BreadcrumbItem");var Q=x(B("piral-core"));function xr(r,e){let[t]=r.filter(a=>a.matcher.test(e));return t}function vr(r,e){let t=e.split("/");for(;t.length>1;){t.pop();let a=t.join("/"),o=I(r,a);if(o)return o}}function I(r,e){if(e)return xr(r,e)||vr(r,e)}function V(r){let e=(0,Q.useGlobalState)(a=>a.registry.breadcrumbs),t=Object.keys(e).map(a=>e[a]);if(t.length>0){let a=I(t,r);if(a){let o=[a],i=I(t,a.settings.parent);for(;i!==void 0;)o.push(i),i=I(t,i.settings.parent);return o.reverse()}}return[]}var j=()=>{var m;let r=(0,T.useLocation)(),e=V(r.pathname),t=e.length-1,a=e[t],{params:o}=(0,T.useRouteMatch)((m=a==null?void 0:a.settings.path)!=null?m:"/"),i=e.map(({settings:n},s)=>{let w=n,{title:u,path:p}=w,c=y(w,["title","path"]),l=`bc_${s}_${n.path}`,d=s===t,b=p.replace(/:([A-Za-z0-9_]+)/g,(v,P)=>{var A;return(A=o[P])!=null?A:v});return U.createElement(Z,f({key:l,current:d,path:b},c),u)});return U.createElement(X,{children:i})};j.displayName="Breadcrumbs";var F={};hr(F,{registerBreadcrumbs:()=>yr,unregisterBreadcrumbs:()=>Rr});function yr(r,e){r.dispatch(t=>g(f({},t),{registry:g(f({},t.registry),{breadcrumbs:f(f({},t.registry.breadcrumbs),e)})}))}function Rr(r,e){r.dispatch(t=>g(f({},t),{registry:g(f({},t.registry),{breadcrumbs:e.reduce((a,o)=>{let n=a,{[o]:i}=n;return y(n,[L(o)])},t.registry.breadcrumbs)})}))}var h=x(B("piral-core"));var Y=x(B("react")),E=x(B("piral-core")),k=r=>Y.createElement(E.ExtensionSlot,{name:"breadcrumbs",params:r,empty:()=>(0,E.defaultRender)(r.children,"default_breadcrumbs")}),rr=r=>(0,E.defaultRender)(r.children);var or=cr();function ur(r){return r.matcher instanceof RegExp?r.matcher:typeof r.matcher=="string"?or(r.matcher):or(r.path)}function Dr(r){let e={},t=0;for(let a of r)e[`global-${t++}`]={pilet:void 0,matcher:ur(a),settings:a};return e}function $r(r){return e=>g(f({},e),{components:f({BreadcrumbItem:rr,BreadcrumbsContainer:k},e.components),registry:g(f({},e.registry),{breadcrumbs:r})})}function Wr(r={}){let{breadcrumbs:e=[]}=r;return t=>(t.defineActions(F),t.dispatch((0,h.withAll)($r(Dr(e)),(0,h.withRootExtension)("piral-breadcrumbs",j))),(a,o)=>{let i=o.name,m=0;return{registerBreadcrumbs(n){let s={};for(let p of n){let u=p,{name:c=m++}=u,l=y(u,["name"]),d=(0,h.buildName)(i,c);s[d]=l}return t.registerBreadcrumbs(s),()=>t.unregisterBreadcrumbs(Object.keys(s))},registerBreadcrumb(n,s){typeof n!="string"&&(s=n,n=m++);let u=(0,h.buildName)(i,n);return t.registerBreadcrumbs({[u]:{pilet:i,matcher:ur(s),settings:s}}),()=>t.unregisterBreadcrumbs([u])},unregisterBreadcrumb(n){let s=(0,h.buildName)(i,n);t.unregisterBreadcrumbs([s])}}})}})();
1
+ (()=>{var pr=Object.create;var C=Object.defineProperty,lr=Object.defineProperties,fr=Object.getOwnPropertyDescriptor,dr=Object.getOwnPropertyDescriptors,br=Object.getOwnPropertyNames,A=Object.getOwnPropertySymbols,gr=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty,M=Object.prototype.propertyIsEnumerable;var z=(r,e,t)=>e in r?C(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,d=(r,e)=>{for(var t in e||(e={}))G.call(e,t)&&z(r,t,e[t]);if(A)for(var t of A(e))M.call(e,t)&&z(r,t,e[t]);return r},g=(r,e)=>lr(r,dr(e)),H=r=>C(r,"__esModule",{value:!0});var B=(r=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(r,{get:(e,t)=>(typeof require!="undefined"?require:e)[t]}):r)(function(r){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+r+'" is not supported')}),K=r=>typeof r=="symbol"?r:r+"",y=(r,e)=>{var t={};for(var a in r)G.call(r,a)&&e.indexOf(a)<0&&(t[a]=r[a]);if(r!=null&&A)for(var a of A(r))e.indexOf(a)<0&&M.call(r,a)&&(t[a]=r[a]);return t};var W=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),hr=(r,e)=>{H(r);for(var t in e)C(r,t,{get:e[t],enumerable:!0})},Br=(r,e,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of br(e))!G.call(r,a)&&a!=="default"&&C(r,a,{get:()=>e[a],enumerable:!(t=fr(e,a))||t.enumerable});return r},x=r=>Br(H(C(r!=null?pr(gr(r)):{},"default",r&&r.__esModule&&"default"in r?{get:()=>r.default,enumerable:!0}:{value:r,enumerable:!0})),r);var tr=W((qr,er)=>{er.exports=Array.isArray||function(r){return Object.prototype.toString.call(r)=="[object Array]"}});var or=W((Jr,R)=>{var T=tr();R.exports=ir;R.exports.parse=N;R.exports.compile=wr;R.exports.tokensToFunction=ar;R.exports.tokensToRegExp=nr;var Er=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function N(r,e){for(var t=[],a=0,c=0,i="",m=e&&e.delimiter||"/",n;(n=Er.exec(r))!=null;){var s=n[0],u=n[1],p=n.index;if(i+=r.slice(c,p),c=p+s.length,u){i+=u[1];continue}var o=r[c],l=n[2],f=n[3],b=n[4],w=n[5],v=n[6],$=n[7];i&&(t.push(i),i="");var P=l!=null&&o!=null&&o!==l,sr=v==="+"||v==="*",mr=v==="?"||v==="*",q=n[2]||m,J=b||w;t.push({name:f||a++,prefix:l||"",delimiter:q,optional:mr,repeat:sr,partial:P,asterisk:!!$,pattern:J?Sr(J):$?".*":"[^"+D(q)+"]+?"})}return c<r.length&&(i+=r.substr(c)),i&&t.push(i),t}function wr(r,e){return ar(N(r,e),e)}function Pr(r){return encodeURI(r).replace(/[\/?#]/g,function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})}function Ar(r){return encodeURI(r).replace(/[?#]/g,function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()})}function ar(r,e){for(var t=new Array(r.length),a=0;a<r.length;a++)typeof r[a]=="object"&&(t[a]=new RegExp("^(?:"+r[a].pattern+")$",L(e)));return function(c,i){for(var m="",n=c||{},s=i||{},u=s.pretty?Pr:encodeURIComponent,p=0;p<r.length;p++){var o=r[p];if(typeof o=="string"){m+=o;continue}var l=n[o.name],f;if(l==null)if(o.optional){o.partial&&(m+=o.prefix);continue}else throw new TypeError('Expected "'+o.name+'" to be defined');if(T(l)){if(!o.repeat)throw new TypeError('Expected "'+o.name+'" to not repeat, but received `'+JSON.stringify(l)+"`");if(l.length===0){if(o.optional)continue;throw new TypeError('Expected "'+o.name+'" to not be empty')}for(var b=0;b<l.length;b++){if(f=u(l[b]),!t[p].test(f))throw new TypeError('Expected all "'+o.name+'" to match "'+o.pattern+'", but received `'+JSON.stringify(f)+"`");m+=(b===0?o.prefix:o.delimiter)+f}continue}if(f=o.asterisk?Ar(l):u(l),!t[p].test(f))throw new TypeError('Expected "'+o.name+'" to match "'+o.pattern+'", but received "'+f+'"');m+=o.prefix+f}return m}}function D(r){return r.replace(/([.+*?=^!:${}()[\]|\/\\])/g,"\\$1")}function Sr(r){return r.replace(/([=!:$\/()])/g,"\\$1")}function O(r,e){return r.keys=e,r}function L(r){return r&&r.sensitive?"":"i"}function Ir(r,e){var t=r.source.match(/\((?!\?)/g);if(t)for(var a=0;a<t.length;a++)e.push({name:a,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,asterisk:!1,pattern:null});return O(r,e)}function Tr(r,e,t){for(var a=[],c=0;c<r.length;c++)a.push(ir(r[c],e,t).source);var i=new RegExp("(?:"+a.join("|")+")",L(t));return O(i,e)}function Dr(r,e,t){return nr(N(r,t),e,t)}function nr(r,e,t){T(e)||(t=e||t,e=[]),t=t||{};for(var a=t.strict,c=t.end!==!1,i="",m=0;m<r.length;m++){var n=r[m];if(typeof n=="string")i+=D(n);else{var s=D(n.prefix),u="(?:"+n.pattern+")";e.push(n),n.repeat&&(u+="(?:"+s+u+")*"),n.optional?n.partial?u=s+"("+u+")?":u="(?:"+s+"("+u+"))?":u=s+"("+u+")",i+=u}}var p=D(t.delimiter||"/"),o=i.slice(-p.length)===p;return a||(i=(o?i.slice(0,-p.length):i)+"(?:"+p+"(?=$))?"),c?i+="$":i+=a&&o?"":"(?="+p+"|$)",O(new RegExp("^"+i,L(t)),e)}function ir(r,e,t){return T(e)||(t=e||t,e=[]),t=t||{},r instanceof RegExp?Ir(r,e):T(r)?Tr(r,e,t):Dr(r,e,t)}});var U=x(B("react")),I=x(B("react-router"));var _=x(B("piral-core")),X=(0,_.getPiralComponent)("BreadcrumbsContainer"),Z=(0,_.getPiralComponent)("BreadcrumbItem");var Q=x(B("piral-core"));function xr(r,e){let[t]=r.filter(a=>a.matcher.test(e));return t}function vr(r,e){let t=e.split("/");for(;t.length>1;){t.pop();let a=t.join("/"),c=S(r,a);if(c)return c}}function S(r,e){if(e)return xr(r,e)||vr(r,e)}function V(r){let e=(0,Q.useGlobalState)(a=>a.registry.breadcrumbs),t=Object.keys(e).map(a=>e[a]);if(t.length>0){let a=S(t,r);if(a){let c=[a],i=S(t,a.settings.parent);for(;i!==void 0;)c.push(i),i=S(t,i.settings.parent);return c.reverse()}}return[]}function yr(r,e,t,a){return typeof r=="function"?r({location:e,path:t,params:a}):r}var j=()=>{var m;let r=(0,I.useLocation)(),e=V(r.pathname),t=e.length-1,a=e[t],{params:c}=(0,I.useRouteMatch)((m=a==null?void 0:a.settings.path)!=null?m:"/"),i=e.map(({settings:n},s)=>{let w=n,{title:u,path:p}=w,o=y(w,["title","path"]),l=`bc_${s}_${n.path}`,f=s===t,b=p.replace(/:(([A-Za-z0-9_]+)\*?)/g,(v,$,P)=>P in c?c[P]||"":v);return U.createElement(Z,d({key:l,current:f,path:b},o),yr(u,r,b,c))});return U.createElement(X,{children:i})};j.displayName="Breadcrumbs";var F={};hr(F,{registerBreadcrumbs:()=>Rr,unregisterBreadcrumbs:()=>Cr});function Rr(r,e){r.dispatch(t=>g(d({},t),{registry:g(d({},t.registry),{breadcrumbs:d(d({},t.registry.breadcrumbs),e)})}))}function Cr(r,e){r.dispatch(t=>g(d({},t),{registry:g(d({},t.registry),{breadcrumbs:e.reduce((a,c)=>{let n=a,{[c]:i}=n;return y(n,[K(c)])},t.registry.breadcrumbs)})}))}var h=x(B("piral-core"));var Y=x(B("react")),E=x(B("piral-core")),k=r=>Y.createElement(E.ExtensionSlot,{name:"breadcrumbs",params:r,empty:()=>(0,E.defaultRender)(r.children,"default_breadcrumbs")}),rr=r=>(0,E.defaultRender)(r.children);var cr=or();function ur(r){return r.matcher instanceof RegExp?r.matcher:typeof r.matcher=="string"?cr(r.matcher):cr(r.path)}function $r(r){let e={},t=0;for(let a of r)e[`global-${t++}`]={pilet:void 0,matcher:ur(a),settings:a};return e}function Gr(r){return e=>g(d({},e),{components:d({BreadcrumbItem:rr,BreadcrumbsContainer:k},e.components),registry:g(d({},e.registry),{breadcrumbs:r})})}function Xr(r={}){let{breadcrumbs:e=[]}=r;return t=>(t.defineActions(F),t.dispatch((0,h.withAll)(Gr($r(e)),(0,h.withRootExtension)("piral-breadcrumbs",j))),(a,c)=>{let i=c.name,m=0;return{registerBreadcrumbs(n){let s={};for(let p of n){let u=p,{name:o=m++}=u,l=y(u,["name"]),f=(0,h.buildName)(i,o);s[f]=l}return t.registerBreadcrumbs(s),()=>t.unregisterBreadcrumbs(Object.keys(s))},registerBreadcrumb(n,s){typeof n!="string"&&(s=n,n=m++);let u=(0,h.buildName)(i,n);return t.registerBreadcrumbs({[u]:{pilet:i,matcher:ur(s),settings:s}}),()=>t.unregisterBreadcrumbs([u])},unregisterBreadcrumb(n){let s=(0,h.buildName)(i,n);t.unregisterBreadcrumbs([s])}}})}})();
@@ -3,6 +3,7 @@ import create from 'zustand';
3
3
  import { render } from '@testing-library/react';
4
4
  import { StateContext } from 'piral-core';
5
5
  import { Breadcrumbs } from './Breadcrumbs';
6
+ import { useRouteMatch } from 'react-router';
6
7
 
7
8
  const MockBcContainer: React.FC<any> = ({ children }) => <div role="container">{children}</div>;
8
9
  MockBcContainer.displayName = 'MockBcContainer';
@@ -16,9 +17,7 @@ jest.mock('react-router', () => ({
16
17
  pathname: '/example',
17
18
  };
18
19
  },
19
- useRouteMatch() {
20
- return {};
21
- },
20
+ useRouteMatch: jest.fn(() => ({})),
22
21
  }));
23
22
 
24
23
  function createMockContainer(breadcrumbs = {}) {
@@ -50,18 +49,18 @@ function createMockContainer(breadcrumbs = {}) {
50
49
  }
51
50
 
52
51
  describe('Piral-Breadcrumb Container component', () => {
53
- it('uses container for a breadcrumbs', () => {
52
+ it('breadcrumbs empty', () => {
54
53
  const { context } = createMockContainer();
55
54
  const node = render(
56
55
  <StateContext.Provider value={context}>
57
56
  <Breadcrumbs />
58
57
  </StateContext.Provider>,
59
58
  );
60
- expect(node.getAllByRole("container").length).toBe(1);
61
- expect(node.queryByRole("dialog")).toBe(null);
59
+ expect(node.getAllByRole('container').length).toBe(1);
60
+ expect(node.queryByRole('dialog')).toBe(null);
62
61
  });
63
62
 
64
- it('uses container and item for each breadcrumb', () => {
63
+ it('breadcrumbs are created successfully', () => {
65
64
  const { context } = createMockContainer({
66
65
  home: {
67
66
  matcher: /^\/$/,
@@ -92,7 +91,134 @@ describe('Piral-Breadcrumb Container component', () => {
92
91
  <Breadcrumbs />
93
92
  </StateContext.Provider>,
94
93
  );
95
- expect(node.getAllByRole("container").length).toBe(1);
96
- expect(node.getAllByRole("dialog").length).toBe(2);
94
+ expect(node.getAllByRole('container').length).toBe(1);
95
+ expect(node.getAllByRole('dialog').length).toBe(2);
96
+ });
97
+
98
+ it('dynamic title function replaces wildcard with route param', () => {
99
+ (useRouteMatch as any).mockReturnValueOnce({ params: { example: 'replacedWildcard' } });
100
+
101
+ const { context } = createMockContainer({
102
+ example: {
103
+ matcher: /^\/example$/,
104
+ settings: {
105
+ path: '/:example*',
106
+ title: ({ path }) => {
107
+ return path;
108
+ },
109
+ parent: '/',
110
+ },
111
+ },
112
+ });
113
+ const node = render(
114
+ <StateContext.Provider value={context}>
115
+ <Breadcrumbs />
116
+ </StateContext.Provider>,
117
+ );
118
+
119
+ expect(node.getAllByRole('container').length).toBe(1);
120
+ expect(node.getAllByRole('dialog').length).toBe(1);
121
+ expect(node.getAllByRole('container')[0].innerHTML).toBe('<div role="dialog">/replacedWildcard</div>');
122
+ });
123
+
124
+ it('dynamic title function no match in params', () => {
125
+ (useRouteMatch as any).mockReturnValueOnce({ params: { imNotHere: 'replacedWildcard' } });
126
+
127
+ const { context } = createMockContainer({
128
+ example: {
129
+ matcher: /^\/example$/,
130
+ settings: {
131
+ path: '/:example*',
132
+ title: ({ path }) => {
133
+ return path;
134
+ },
135
+ parent: '/',
136
+ },
137
+ },
138
+ });
139
+ const node = render(
140
+ <StateContext.Provider value={context}>
141
+ <Breadcrumbs />
142
+ </StateContext.Provider>,
143
+ );
144
+
145
+ expect(node.getAllByRole('container').length).toBe(1);
146
+ expect(node.getAllByRole('dialog').length).toBe(1);
147
+ expect(node.getAllByRole('container')[0].innerHTML).toBe('<div role="dialog">/:example*</div>');
148
+ });
149
+
150
+ it('dynamic title function with falsely route param', () => {
151
+ (useRouteMatch as any).mockReturnValueOnce({ params: { example: false } });
152
+
153
+ const { context } = createMockContainer({
154
+ example: {
155
+ matcher: /^\/example$/,
156
+ settings: {
157
+ path: '/:example*',
158
+ title: ({ path }) => {
159
+ return path;
160
+ },
161
+ parent: '/',
162
+ },
163
+ },
164
+ });
165
+ const node = render(
166
+ <StateContext.Provider value={context}>
167
+ <Breadcrumbs />
168
+ </StateContext.Provider>,
169
+ );
170
+
171
+ expect(node.getAllByRole('container').length).toBe(1);
172
+ expect(node.getAllByRole('dialog').length).toBe(1);
173
+ expect(node.getAllByRole('container')[0].innerHTML).toBe('<div role="dialog">/</div>');
174
+ });
175
+
176
+ it('dynamic title function with static title', () => {
177
+ (useRouteMatch as any).mockReturnValueOnce({ params: { imNotHere: 'replacedWildcard' } });
178
+
179
+ const { context } = createMockContainer({
180
+ example: {
181
+ matcher: /^\/example$/,
182
+ settings: {
183
+ path: '/example',
184
+ title: ({ path }) => {
185
+ return 'My Path';
186
+ },
187
+ parent: '/',
188
+ },
189
+ },
190
+ });
191
+ const node = render(
192
+ <StateContext.Provider value={context}>
193
+ <Breadcrumbs />
194
+ </StateContext.Provider>,
195
+ );
196
+
197
+ expect(node.getAllByRole('container').length).toBe(1);
198
+ expect(node.getAllByRole('dialog').length).toBe(1);
199
+ expect(node.getAllByRole('container')[0].innerHTML).toBe('<div role="dialog">My Path</div>');
200
+ });
201
+
202
+ it('static title', () => {
203
+ (useRouteMatch as any).mockReturnValueOnce({ params: {} });
204
+
205
+ const { context } = createMockContainer({
206
+ example: {
207
+ matcher: /^\/example$/,
208
+ settings: {
209
+ path: '/:example*',
210
+ title: 'My Path',
211
+ parent: '/',
212
+ },
213
+ },
214
+ });
215
+ const node = render(
216
+ <StateContext.Provider value={context}>
217
+ <Breadcrumbs />
218
+ </StateContext.Provider>,
219
+ );
220
+
221
+ expect(node.getAllByRole('container').length).toBe(1);
222
+ expect(node.getAllByRole('container')[0].innerHTML).toBe('<div role="dialog">My Path</div>');
97
223
  });
98
224
  });
@@ -2,6 +2,21 @@ import * as React from 'react';
2
2
  import { useLocation, useRouteMatch } from 'react-router';
3
3
  import { PiralBreadcrumbsContainer, PiralBreadcrumbItem } from './components';
4
4
  import { useBreadcrumbs } from './useBreadcrumbs';
5
+ import { BreadcrumbSettings } from './types';
6
+ import { Location } from 'history';
7
+
8
+ function getContent(
9
+ title: BreadcrumbSettings['title'],
10
+ location: Location,
11
+ path: string,
12
+ params: Record<string, string>,
13
+ ) {
14
+ if (typeof title === 'function') {
15
+ return title({ location, path, params });
16
+ }
17
+
18
+ return title;
19
+ }
5
20
 
6
21
  export const Breadcrumbs: React.FC = () => {
7
22
  const location = useLocation();
@@ -14,11 +29,17 @@ export const Breadcrumbs: React.FC = () => {
14
29
  const { title, path, ...props } = settings;
15
30
  const key = `bc_${i}_${settings.path}`;
16
31
  const current = i === currentIndex;
17
- const computedPath = path.replace(/:([A-Za-z0-9_]+)/g, (s, id) => params[id] ?? s);
32
+ const computedPath = path.replace(/:(([A-Za-z0-9_]+)\*?)/g, (s, _, id) => {
33
+ if (id in params) {
34
+ return params[id] || '';
35
+ }
36
+
37
+ return s;
38
+ });
18
39
 
19
40
  return (
20
41
  <PiralBreadcrumbItem key={key} current={current} path={computedPath} {...props}>
21
- {title}
42
+ {getContent(title, location, computedPath, params)}
22
43
  </PiralBreadcrumbItem>
23
44
  );
24
45
  });
@@ -16,7 +16,7 @@ describe('Breadcrumbs Actions Module', () => {
16
16
  registerBreadcrumbs(ctx, {
17
17
  foo: 10 as any,
18
18
  });
19
- expect((state.getState())).toEqual({
19
+ expect(state.getState()).toEqual({
20
20
  foo: 5,
21
21
  registry: {
22
22
  foo: 5,
@@ -26,7 +26,7 @@ describe('Breadcrumbs Actions Module', () => {
26
26
  },
27
27
  });
28
28
  unregisterBreadcrumbs(ctx, ['foo']);
29
- expect((state.getState())).toEqual({
29
+ expect(state.getState()).toEqual({
30
30
  foo: 5,
31
31
  registry: {
32
32
  foo: 5,
@@ -86,4 +86,21 @@ describe('Create Breadcrumb API Extensions', () => {
86
86
  const ids = Object.keys(container.context.registerBreadcrumbs.mock.calls[0][0]);
87
87
  expect(container.context.unregisterBreadcrumbs.mock.calls[0][0]).toEqual(ids);
88
88
  });
89
+
90
+ it('createBreadcrumsApi can use dynamic function as breadcrumb title', () => {
91
+ const container = createMockContainer();
92
+ container.context.registerBreadcrumbs = jest.fn();
93
+ container.context.unregisterBreadcrumbs = jest.fn();
94
+ const api = createApi(container);
95
+ const dispose = api.registerBreadcrumb({
96
+ title: ({ path }) => path,
97
+ path: '/example',
98
+ });
99
+ expect(container.context.registerBreadcrumbs).toHaveBeenCalledTimes(1);
100
+ expect(container.context.unregisterBreadcrumbs).toHaveBeenCalledTimes(0);
101
+ dispose();
102
+ expect(container.context.registerBreadcrumbs).toHaveBeenCalledTimes(1);
103
+ const ids = Object.keys(container.context.registerBreadcrumbs.mock.calls[0][0]);
104
+ expect(container.context.unregisterBreadcrumbs.mock.calls[0][0]).toEqual(ids);
105
+ });
89
106
  });
package/src/types.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { ComponentType, ReactNode } from 'react';
2
2
  import type { Dict, BaseRegistration, RegistrationDisposer } from 'piral-core';
3
+ import type { Location } from 'history';
3
4
 
4
5
  declare module 'piral-core/lib/types/custom' {
5
6
  interface PiletCustomApi extends PiletBreadcrumbsApi {}
@@ -12,6 +13,7 @@ declare module 'piral-core/lib/types/custom' {
12
13
  * @param values The breadcrumbs to register.
13
14
  */
14
15
  registerBreadcrumbs(values: Dict<BreadcrumbRegistration>): void;
16
+
15
17
  /**
16
18
  * Unregisters an existing breadcrumb.
17
19
  * @param name The name of the breadcrumb to be removed.
@@ -58,6 +60,12 @@ export interface BreadcrumbItemProps extends Omit<BreadcrumbSettings, 'title'> {
58
60
 
59
61
  export interface PiralCustomBreadcrumbSettings {}
60
62
 
63
+ export interface BreadcrumbTitleParams {
64
+ location: Location;
65
+ path: string;
66
+ params: Record<string, string>;
67
+ }
68
+
61
69
  export interface BreadcrumbSettings extends PiralCustomBreadcrumbSettings {
62
70
  /**
63
71
  * Gets the path of breadcrumb for navigation purposes.
@@ -83,7 +91,7 @@ export interface BreadcrumbSettings extends PiralCustomBreadcrumbSettings {
83
91
  /**
84
92
  * The title of the breadcrumb.
85
93
  */
86
- title: ReactNode;
94
+ title: ReactNode | ((params: BreadcrumbTitleParams) => ReactNode);
87
95
  }
88
96
 
89
97
  export interface BreadcrumbRegistration extends BaseRegistration {
@@ -96,12 +104,14 @@ export interface PiletBreadcrumbsApi {
96
104
  * Registers a set of breadcrumbs.
97
105
  * @param values The different breadcrumb settings.
98
106
  */
99
- registerBreadcrumbs(values: Array<{ name?: string; } & BreadcrumbSettings>): RegistrationDisposer;
107
+ registerBreadcrumbs(values: Array<{ name?: string } & BreadcrumbSettings>): RegistrationDisposer;
108
+
100
109
  /**
101
110
  * Registers a breadcrumb with the provided settings.
102
111
  * @param settings The settings for configuring the breadcrumb.
103
112
  */
104
113
  registerBreadcrumb(settings: BreadcrumbSettings): RegistrationDisposer;
114
+
105
115
  /**
106
116
  * Registers a named breadcrumb with the provided settings.
107
117
  * The name has to be unique within the current pilet.
@@ -109,6 +119,7 @@ export interface PiletBreadcrumbsApi {
109
119
  * @param settings The settings for configuring the breadcrumb.
110
120
  */
111
121
  registerBreadcrumb(name: string, settings: BreadcrumbSettings): RegistrationDisposer;
122
+
112
123
  /**
113
124
  * Unregisters a breadcrumb known by the given name.
114
125
  * Only previously registered tiles can be unregistered.