@rytass/bpm-core-react 0.3.2 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  Releases are managed by [`nx release`](https://nx.dev/recipes/nx-release) with
9
9
  Conventional Commits — see `nx.json` for the release config.
10
10
 
11
+ ## 0.3.4 — 2026-05-28
12
+
13
+ ### Documentation
14
+
15
+ - **README "Mounting BPM under a non-root URL prefix"** added. Shows
16
+ the exhaustive `createPrefixedRoutes(prefix)` factory covering all
17
+ **19** `BPMRoutes` entries (previously the README only sketched
18
+ 2-3). Spreading `createDefaultBPMRoutes()` first means new BPMCore
19
+ versions that add routes never silently regress consumer hosts.
20
+
21
+ ### Why a patch
22
+
23
+ Documentation-only. No source change.
24
+
25
+ ## 0.3.3 — 2026-05-28
26
+
27
+ ### Fixed
28
+
29
+ - **Dist `.d.ts` files leaked workspace-source paths.** The 0.3.0–0.3.2
30
+ release shipped declaration files that contained relative imports back
31
+ into the vendor's monorepo (e.g. `import { ApiMember } from
32
+ '../../libs/bpm-core-client/src/index.ts'`), which broke `tsc` for any
33
+ consumer that didn't have BPMCore's source on disk at that exact
34
+ relative path. The build now passes `compilerOptions.paths: {}` to
35
+ `vite-plugin-dts` so the published types reference packages by their
36
+ npm names (`@rytass/bpm-core-client`) rather than by resolved aliases.
37
+
38
+ ### Added
39
+
40
+ - **`BPMNextProviders` props are now typed and forwarded.** The
41
+ `loginPath`, `publicPaths`, and `locale` props were always accepted by
42
+ the inner `<Providers>` but the `next` subpath wrapper hid them. They
43
+ are now part of the exported `BPMNextProvidersProps` interface and
44
+ forwarded through. Default `loginPath` remains `'/login'`, so hosts
45
+ with a different auth route must pass their override explicitly.
46
+
47
+ ### Documentation
48
+
49
+ - `BPMRoutes.caseDetail` and `BPMRoutes.caseNew(templateId?)` JSDoc
50
+ carries `@example` annotations showing the default factory's literal
51
+ paths so consumers can see what they're overriding without reading
52
+ the source.
53
+
54
+ ### Why a patch
55
+
56
+ The d.ts fix only affected consumers' type-check experience — runtime
57
+ behavior didn't change. The `BPMNextProviders` props forwarding is
58
+ additive (props were silently dropped before, now they work).
59
+
11
60
  ## 0.3.2 — 2026-05-28
12
61
 
13
62
  ### Added
package/README.md CHANGED
@@ -63,6 +63,60 @@ function MyLoginPage() {
63
63
 
64
64
  For SPA / Remix / Tanstack Router hosts, supply a `RouterAdapter` that bridges your router primitives.
65
65
 
66
+ ### Mounting BPM under a non-root URL prefix
67
+
68
+ If your host already owns the `/` namespace (Shuttle, an existing
69
+ admin console, etc.), wrap the BPM tree in `<BPMRoutesProvider>` and
70
+ override every internal cross-link to a prefixed path. The full
71
+ `BPMRoutes` contract has **19 entries** — overriding only some leaves
72
+ the rest pointing at the unprefixed defaults, which usually 404s on
73
+ your host. Use a small factory to keep the override exhaustive:
74
+
75
+ ```tsx
76
+ import {
77
+ BPMRoutesProvider,
78
+ createDefaultBPMRoutes,
79
+ type BPMRoutes,
80
+ } from '@rytass/bpm-core-react/next';
81
+
82
+ function createPrefixedRoutes(prefix: string): BPMRoutes {
83
+ const trim = prefix.replace(/\/$/, '');
84
+ return {
85
+ ...createDefaultBPMRoutes(), // safety net for any future routes
86
+ dashboard: () => `${trim}`,
87
+ inbox: () => `${trim}/inbox`,
88
+ sent: () => `${trim}/sent`,
89
+ cc: () => `${trim}/cc`,
90
+ search: () => `${trim}/search`,
91
+ delegations: () => `${trim}/delegations`,
92
+ notifications: () => `${trim}/notifications`,
93
+ caseDetail: (id) => `${trim}/instances/${id}`,
94
+ caseNew: (templateId) => templateId
95
+ ? `${trim}/instances/new?templateId=${encodeURIComponent(templateId)}`
96
+ : `${trim}/instances/new`,
97
+ templates: () => `${trim}/templates`,
98
+ templateDesigner: (id) => `${trim}/templates/${id}/designer`,
99
+ templateVersions: (id) => `${trim}/templates/${id}/versions`,
100
+ templateCategories: () => `${trim}/templates/categories`,
101
+ forms: () => `${trim}/forms`,
102
+ formBuilder: (id) => `${trim}/forms/${id}/builder`,
103
+ notificationSettings: () => `${trim}/settings/notifications`,
104
+ adminOrgs: () => `${trim}/admin/orgs`,
105
+ adminUsers: () => `${trim}/admin/users`,
106
+ adminDelegations: () => `${trim}/admin/delegations`,
107
+ };
108
+ }
109
+
110
+ // In your layout:
111
+ <BPMRoutesProvider value={createPrefixedRoutes('/operations/approval')}>
112
+ <BPMNextProviders>{children}</BPMNextProviders>
113
+ </BPMRoutesProvider>
114
+ ```
115
+
116
+ `createDefaultBPMRoutes()` is the source of truth for the route shape;
117
+ spreading it first means new BPMCore versions that add routes never
118
+ silently regress your host.
119
+
66
120
  ## License
67
121
 
68
122
  MIT
@@ -1 +1 @@
1
- {"version":3,"file":"routes-config-2aKbWq2H.cjs","names":[],"sources":["../../src/lib/routes-config.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useMemo, type ReactNode } from 'react';\n\n/**\n * Framework-agnostic path mapping every BPM view uses for internal\n * cross-navigation. When a host embeds BPM under a non-root prefix\n * (e.g. `/workspace/bpm/*`) it provides its own implementation through\n * `<BPMRoutesProvider value={...}>`; otherwise the default factory\n * preserves the historical `/instances/:id`, `/templates`, etc. paths.\n *\n * Function-shape (instead of string templates) means:\n * - Optional and multi-param routes can branch on argument presence\n * (`caseNew(templateId?)`).\n * - Query-string composition stays inside the host's resolver, not the\n * view.\n * - TypeScript flags missing arguments at compile time.\n *\n * Mirror sibling: {@link RouterAdapter} owns *navigation primitives*\n * (`push`, `replace`, `pathname`); `BPMRoutes` owns *path strings*. The\n * two compose: views call `router.push(routes.caseDetail(id))`.\n */\nexport interface BPMRoutes {\n /** Workflow dashboard landing. Used by sidebar + dashboard tiles. */\n dashboard(): string;\n /** Inbox (待簽) — pending tasks assigned to the current member. */\n inbox(): string;\n /** Sent (我發起的) — instances the current member initiated. */\n sent(): string;\n /** CC (抄送給我) — instances the current member is copied on. */\n cc(): string;\n /** Cross-view search. */\n search(): string;\n /** Personal delegation rules. */\n delegations(): string;\n /** Notification list. */\n notifications(): string;\n\n /** Detail page for one approval instance. */\n caseDetail(instanceId: string): string;\n /**\n * Launch a new approval instance. When `templateId` is passed, the\n * launch form is pre-populated for that template.\n */\n caseNew(templateId?: string): string;\n\n /** Template index. */\n templates(): string;\n /** Template designer (xyflow canvas). */\n templateDesigner(templateId: string): string;\n /** Template version history. */\n templateVersions(templateId: string): string;\n /** Template categories admin. */\n templateCategories(): string;\n\n /** Form definitions index. */\n forms(): string;\n /** Form-builder (CodeMirror schema editor + preview). */\n formBuilder(formId: string): string;\n\n /** Per-member notification preferences. */\n notificationSettings(): string;\n\n /** Admin: organization tree management. */\n adminOrgs(): string;\n /** Admin: member directory mapping. */\n adminUsers(): string;\n /** Admin: delegation rule management. */\n adminDelegations(): string;\n}\n\n/**\n * Factory for the default `BPMRoutes` value. Reproduces the exact path\n * literals BPM views used before `BPMRoutesContext` existed, so existing\n * hosts (no provider mounted) keep working unchanged.\n */\nexport function createDefaultBPMRoutes(): BPMRoutes {\n return {\n dashboard: () => '/dashboard',\n inbox: () => '/inbox',\n sent: () => '/sent',\n cc: () => '/cc',\n search: () => '/search',\n delegations: () => '/delegations',\n notifications: () => '/notifications',\n\n caseDetail: (instanceId) => `/instances/${instanceId}`,\n caseNew: (templateId) =>\n templateId\n ? `/instances/new?templateId=${encodeURIComponent(templateId)}`\n : '/instances/new',\n\n templates: () => '/templates',\n templateDesigner: (templateId) => `/templates/${templateId}/designer`,\n templateVersions: (templateId) => `/templates/${templateId}/versions`,\n templateCategories: () => '/templates/categories',\n\n forms: () => '/forms',\n formBuilder: (formId) => `/forms/${formId}/builder`,\n\n notificationSettings: () => '/settings/notifications',\n\n adminOrgs: () => '/admin/orgs',\n adminUsers: () => '/admin/users',\n adminDelegations: () => '/admin/delegations',\n };\n}\n\nconst BPMRoutesContext = createContext<BPMRoutes | null>(null);\n\nexport interface BPMRoutesProviderProps {\n /**\n * Override the path mapping. Provide a full implementation, or spread\n * the default and override individual entries:\n *\n * ```tsx\n * <BPMRoutesProvider value={{\n * ...createDefaultBPMRoutes(),\n * caseDetail: (id) => `/workspace/cases/${id}`,\n * }}>\n * ```\n */\n readonly value?: BPMRoutes;\n readonly children: ReactNode;\n}\n\n/**\n * Wraps the BPM React tree with a {@link BPMRoutes} value. Mounting the\n * provider is **optional** — `useBPMRoutes()` falls back to\n * {@link createDefaultBPMRoutes} when no provider is present. Use it\n * only when the host needs to remap BPM's internal paths.\n */\nexport function BPMRoutesProvider({\n value,\n children,\n}: BPMRoutesProviderProps): React.ReactElement {\n const resolved = useMemo(() => value ?? createDefaultBPMRoutes(), [value]);\n return (\n <BPMRoutesContext.Provider value={resolved}>\n {children}\n </BPMRoutesContext.Provider>\n );\n}\n\n/**\n * Reads the host-configured {@link BPMRoutes}. Falls back to\n * {@link createDefaultBPMRoutes} when no `<BPMRoutesProvider>` ancestor\n * is mounted, so views remain self-contained.\n */\nexport function useBPMRoutes(): BPMRoutes {\n const value = useContext(BPMRoutesContext);\n return value ?? DEFAULT_ROUTES;\n}\n\nconst DEFAULT_ROUTES: BPMRoutes = createDefaultBPMRoutes();\n"],"mappings":"mEA4EA,SAAgB,GAAoC,CAClD,MAAO,CACL,cAAiB,aACjB,UAAa,SACb,SAAY,QACZ,OAAU,MACV,WAAc,UACd,gBAAmB,eACnB,kBAAqB,iBAErB,WAAa,GAAe,cAAc,IAC1C,QAAU,GACR,EACI,6BAA6B,mBAAmB,CAAU,IAC1D,iBAEN,cAAiB,aACjB,iBAAmB,GAAe,cAAc,EAAW,WAC3D,iBAAmB,GAAe,cAAc,EAAW,WAC3D,uBAA0B,wBAE1B,UAAa,SACb,YAAc,GAAW,UAAU,EAAO,UAE1C,yBAA4B,0BAE5B,cAAiB,cACjB,eAAkB,eAClB,qBAAwB,oBAC1B,CACF,CAEA,IAAM,GAAA,EAAA,EAAA,eAAmD,IAAI,EAwB7D,SAAgB,EAAkB,CAChC,QACA,YAC6C,CAC7C,IAAM,GAAA,EAAA,EAAA,aAAyB,GAAS,EAAuB,EAAG,CAAC,CAAK,CAAC,EACzE,OACE,EAAA,EAAA,KAAC,EAAiB,SAAlB,CAA2B,MAAO,EAC/B,UACwB,CAAA,CAE/B,CAOA,SAAgB,GAA0B,CAExC,OAAA,EAAA,EAAA,YADyB,CAClB,GAAS,CAClB,CAEA,IAAM,EAA4B,EAAuB"}
1
+ {"version":3,"file":"routes-config-2aKbWq2H.cjs","names":[],"sources":["../../src/lib/routes-config.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useMemo, type ReactNode } from 'react';\n\n/**\n * Framework-agnostic path mapping every BPM view uses for internal\n * cross-navigation. When a host embeds BPM under a non-root prefix\n * (e.g. `/workspace/bpm/*`) it provides its own implementation through\n * `<BPMRoutesProvider value={...}>`; otherwise the default factory\n * preserves the historical `/instances/:id`, `/templates`, etc. paths.\n *\n * Function-shape (instead of string templates) means:\n * - Optional and multi-param routes can branch on argument presence\n * (`caseNew(templateId?)`).\n * - Query-string composition stays inside the host's resolver, not the\n * view.\n * - TypeScript flags missing arguments at compile time.\n *\n * Mirror sibling: {@link RouterAdapter} owns *navigation primitives*\n * (`push`, `replace`, `pathname`); `BPMRoutes` owns *path strings*. The\n * two compose: views call `router.push(routes.caseDetail(id))`.\n */\nexport interface BPMRoutes {\n /** Workflow dashboard landing. Used by sidebar + dashboard tiles. */\n dashboard(): string;\n /** Inbox (待簽) — pending tasks assigned to the current member. */\n inbox(): string;\n /** Sent (我發起的) — instances the current member initiated. */\n sent(): string;\n /** CC (抄送給我) — instances the current member is copied on. */\n cc(): string;\n /** Cross-view search. */\n search(): string;\n /** Personal delegation rules. */\n delegations(): string;\n /** Notification list. */\n notifications(): string;\n\n /**\n * Detail page for one approval instance.\n *\n * @example default → `/instances/abc123`\n */\n caseDetail(instanceId: string): string;\n /**\n * Launch a new approval instance. When `templateId` is passed, the\n * launch form is pre-populated for that template — by default this is\n * appended as a `?templateId=` query string so the path itself stays\n * stable for routing.\n *\n * @example default `caseNew()` → `/instances/new`\n * @example default `caseNew('tpl-1')` → `/instances/new?templateId=tpl-1`\n */\n caseNew(templateId?: string): string;\n\n /** Template index. */\n templates(): string;\n /** Template designer (xyflow canvas). */\n templateDesigner(templateId: string): string;\n /** Template version history. */\n templateVersions(templateId: string): string;\n /** Template categories admin. */\n templateCategories(): string;\n\n /** Form definitions index. */\n forms(): string;\n /** Form-builder (CodeMirror schema editor + preview). */\n formBuilder(formId: string): string;\n\n /** Per-member notification preferences. */\n notificationSettings(): string;\n\n /** Admin: organization tree management. */\n adminOrgs(): string;\n /** Admin: member directory mapping. */\n adminUsers(): string;\n /** Admin: delegation rule management. */\n adminDelegations(): string;\n}\n\n/**\n * Factory for the default `BPMRoutes` value. Reproduces the exact path\n * literals BPM views used before `BPMRoutesContext` existed, so existing\n * hosts (no provider mounted) keep working unchanged.\n */\nexport function createDefaultBPMRoutes(): BPMRoutes {\n return {\n dashboard: () => '/dashboard',\n inbox: () => '/inbox',\n sent: () => '/sent',\n cc: () => '/cc',\n search: () => '/search',\n delegations: () => '/delegations',\n notifications: () => '/notifications',\n\n caseDetail: (instanceId) => `/instances/${instanceId}`,\n caseNew: (templateId) =>\n templateId\n ? `/instances/new?templateId=${encodeURIComponent(templateId)}`\n : '/instances/new',\n\n templates: () => '/templates',\n templateDesigner: (templateId) => `/templates/${templateId}/designer`,\n templateVersions: (templateId) => `/templates/${templateId}/versions`,\n templateCategories: () => '/templates/categories',\n\n forms: () => '/forms',\n formBuilder: (formId) => `/forms/${formId}/builder`,\n\n notificationSettings: () => '/settings/notifications',\n\n adminOrgs: () => '/admin/orgs',\n adminUsers: () => '/admin/users',\n adminDelegations: () => '/admin/delegations',\n };\n}\n\nconst BPMRoutesContext = createContext<BPMRoutes | null>(null);\n\nexport interface BPMRoutesProviderProps {\n /**\n * Override the path mapping. Provide a full implementation, or spread\n * the default and override individual entries:\n *\n * ```tsx\n * <BPMRoutesProvider value={{\n * ...createDefaultBPMRoutes(),\n * caseDetail: (id) => `/workspace/cases/${id}`,\n * }}>\n * ```\n */\n readonly value?: BPMRoutes;\n readonly children: ReactNode;\n}\n\n/**\n * Wraps the BPM React tree with a {@link BPMRoutes} value. Mounting the\n * provider is **optional** — `useBPMRoutes()` falls back to\n * {@link createDefaultBPMRoutes} when no provider is present. Use it\n * only when the host needs to remap BPM's internal paths.\n */\nexport function BPMRoutesProvider({\n value,\n children,\n}: BPMRoutesProviderProps): React.ReactElement {\n const resolved = useMemo(() => value ?? createDefaultBPMRoutes(), [value]);\n return (\n <BPMRoutesContext.Provider value={resolved}>\n {children}\n </BPMRoutesContext.Provider>\n );\n}\n\n/**\n * Reads the host-configured {@link BPMRoutes}. Falls back to\n * {@link createDefaultBPMRoutes} when no `<BPMRoutesProvider>` ancestor\n * is mounted, so views remain self-contained.\n */\nexport function useBPMRoutes(): BPMRoutes {\n const value = useContext(BPMRoutesContext);\n return value ?? DEFAULT_ROUTES;\n}\n\nconst DEFAULT_ROUTES: BPMRoutes = createDefaultBPMRoutes();\n"],"mappings":"mEAqFA,SAAgB,GAAoC,CAClD,MAAO,CACL,cAAiB,aACjB,UAAa,SACb,SAAY,QACZ,OAAU,MACV,WAAc,UACd,gBAAmB,eACnB,kBAAqB,iBAErB,WAAa,GAAe,cAAc,IAC1C,QAAU,GACR,EACI,6BAA6B,mBAAmB,CAAU,IAC1D,iBAEN,cAAiB,aACjB,iBAAmB,GAAe,cAAc,EAAW,WAC3D,iBAAmB,GAAe,cAAc,EAAW,WAC3D,uBAA0B,wBAE1B,UAAa,SACb,YAAc,GAAW,UAAU,EAAO,UAE1C,yBAA4B,0BAE5B,cAAiB,cACjB,eAAkB,eAClB,qBAAwB,oBAC1B,CACF,CAEA,IAAM,GAAA,EAAA,EAAA,eAAmD,IAAI,EAwB7D,SAAgB,EAAkB,CAChC,QACA,YAC6C,CAC7C,IAAM,GAAA,EAAA,EAAA,aAAyB,GAAS,EAAuB,EAAG,CAAC,CAAK,CAAC,EACzE,OACE,EAAA,EAAA,KAAC,EAAiB,SAAlB,CAA2B,MAAO,EAC/B,UACwB,CAAA,CAE/B,CAOA,SAAgB,GAA0B,CAExC,OAAA,EAAA,EAAA,YADyB,CAClB,GAAS,CAClB,CAEA,IAAM,EAA4B,EAAuB"}
@@ -1 +1 @@
1
- {"version":3,"file":"routes-config-dxahImVe.js","names":[],"sources":["../../src/lib/routes-config.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useMemo, type ReactNode } from 'react';\n\n/**\n * Framework-agnostic path mapping every BPM view uses for internal\n * cross-navigation. When a host embeds BPM under a non-root prefix\n * (e.g. `/workspace/bpm/*`) it provides its own implementation through\n * `<BPMRoutesProvider value={...}>`; otherwise the default factory\n * preserves the historical `/instances/:id`, `/templates`, etc. paths.\n *\n * Function-shape (instead of string templates) means:\n * - Optional and multi-param routes can branch on argument presence\n * (`caseNew(templateId?)`).\n * - Query-string composition stays inside the host's resolver, not the\n * view.\n * - TypeScript flags missing arguments at compile time.\n *\n * Mirror sibling: {@link RouterAdapter} owns *navigation primitives*\n * (`push`, `replace`, `pathname`); `BPMRoutes` owns *path strings*. The\n * two compose: views call `router.push(routes.caseDetail(id))`.\n */\nexport interface BPMRoutes {\n /** Workflow dashboard landing. Used by sidebar + dashboard tiles. */\n dashboard(): string;\n /** Inbox (待簽) — pending tasks assigned to the current member. */\n inbox(): string;\n /** Sent (我發起的) — instances the current member initiated. */\n sent(): string;\n /** CC (抄送給我) — instances the current member is copied on. */\n cc(): string;\n /** Cross-view search. */\n search(): string;\n /** Personal delegation rules. */\n delegations(): string;\n /** Notification list. */\n notifications(): string;\n\n /** Detail page for one approval instance. */\n caseDetail(instanceId: string): string;\n /**\n * Launch a new approval instance. When `templateId` is passed, the\n * launch form is pre-populated for that template.\n */\n caseNew(templateId?: string): string;\n\n /** Template index. */\n templates(): string;\n /** Template designer (xyflow canvas). */\n templateDesigner(templateId: string): string;\n /** Template version history. */\n templateVersions(templateId: string): string;\n /** Template categories admin. */\n templateCategories(): string;\n\n /** Form definitions index. */\n forms(): string;\n /** Form-builder (CodeMirror schema editor + preview). */\n formBuilder(formId: string): string;\n\n /** Per-member notification preferences. */\n notificationSettings(): string;\n\n /** Admin: organization tree management. */\n adminOrgs(): string;\n /** Admin: member directory mapping. */\n adminUsers(): string;\n /** Admin: delegation rule management. */\n adminDelegations(): string;\n}\n\n/**\n * Factory for the default `BPMRoutes` value. Reproduces the exact path\n * literals BPM views used before `BPMRoutesContext` existed, so existing\n * hosts (no provider mounted) keep working unchanged.\n */\nexport function createDefaultBPMRoutes(): BPMRoutes {\n return {\n dashboard: () => '/dashboard',\n inbox: () => '/inbox',\n sent: () => '/sent',\n cc: () => '/cc',\n search: () => '/search',\n delegations: () => '/delegations',\n notifications: () => '/notifications',\n\n caseDetail: (instanceId) => `/instances/${instanceId}`,\n caseNew: (templateId) =>\n templateId\n ? `/instances/new?templateId=${encodeURIComponent(templateId)}`\n : '/instances/new',\n\n templates: () => '/templates',\n templateDesigner: (templateId) => `/templates/${templateId}/designer`,\n templateVersions: (templateId) => `/templates/${templateId}/versions`,\n templateCategories: () => '/templates/categories',\n\n forms: () => '/forms',\n formBuilder: (formId) => `/forms/${formId}/builder`,\n\n notificationSettings: () => '/settings/notifications',\n\n adminOrgs: () => '/admin/orgs',\n adminUsers: () => '/admin/users',\n adminDelegations: () => '/admin/delegations',\n };\n}\n\nconst BPMRoutesContext = createContext<BPMRoutes | null>(null);\n\nexport interface BPMRoutesProviderProps {\n /**\n * Override the path mapping. Provide a full implementation, or spread\n * the default and override individual entries:\n *\n * ```tsx\n * <BPMRoutesProvider value={{\n * ...createDefaultBPMRoutes(),\n * caseDetail: (id) => `/workspace/cases/${id}`,\n * }}>\n * ```\n */\n readonly value?: BPMRoutes;\n readonly children: ReactNode;\n}\n\n/**\n * Wraps the BPM React tree with a {@link BPMRoutes} value. Mounting the\n * provider is **optional** — `useBPMRoutes()` falls back to\n * {@link createDefaultBPMRoutes} when no provider is present. Use it\n * only when the host needs to remap BPM's internal paths.\n */\nexport function BPMRoutesProvider({\n value,\n children,\n}: BPMRoutesProviderProps): React.ReactElement {\n const resolved = useMemo(() => value ?? createDefaultBPMRoutes(), [value]);\n return (\n <BPMRoutesContext.Provider value={resolved}>\n {children}\n </BPMRoutesContext.Provider>\n );\n}\n\n/**\n * Reads the host-configured {@link BPMRoutes}. Falls back to\n * {@link createDefaultBPMRoutes} when no `<BPMRoutesProvider>` ancestor\n * is mounted, so views remain self-contained.\n */\nexport function useBPMRoutes(): BPMRoutes {\n const value = useContext(BPMRoutesContext);\n return value ?? DEFAULT_ROUTES;\n}\n\nconst DEFAULT_ROUTES: BPMRoutes = createDefaultBPMRoutes();\n"],"mappings":";;;;AA4EA,SAAgB,IAAoC;CAClD,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,YAAY;EACZ,UAAU;EACV,cAAc;EACd,mBAAmB;EACnB,qBAAqB;EAErB,aAAa,MAAe,cAAc;EAC1C,UAAU,MACR,IACI,6BAA6B,mBAAmB,CAAU,MAC1D;EAEN,iBAAiB;EACjB,mBAAmB,MAAe,cAAc,EAAW;EAC3D,mBAAmB,MAAe,cAAc,EAAW;EAC3D,0BAA0B;EAE1B,aAAa;EACb,cAAc,MAAW,UAAU,EAAO;EAE1C,4BAA4B;EAE5B,iBAAiB;EACjB,kBAAkB;EAClB,wBAAwB;CAC1B;AACF;AAEA,IAAM,IAAmB,EAAgC,IAAI;AAwB7D,SAAgB,EAAkB,EAChC,UACA,eAC6C;CAC7C,IAAM,IAAW,QAAc,KAAS,EAAuB,GAAG,CAAC,CAAK,CAAC;CACzE,OACE,kBAAC,EAAiB,UAAlB;EAA2B,OAAO;EAC/B;CACwB,CAAA;AAE/B;AAOA,SAAgB,IAA0B;CAExC,OADc,EAAW,CAClB,KAAS;AAClB;AAEA,IAAM,IAA4B,EAAuB"}
1
+ {"version":3,"file":"routes-config-dxahImVe.js","names":[],"sources":["../../src/lib/routes-config.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useMemo, type ReactNode } from 'react';\n\n/**\n * Framework-agnostic path mapping every BPM view uses for internal\n * cross-navigation. When a host embeds BPM under a non-root prefix\n * (e.g. `/workspace/bpm/*`) it provides its own implementation through\n * `<BPMRoutesProvider value={...}>`; otherwise the default factory\n * preserves the historical `/instances/:id`, `/templates`, etc. paths.\n *\n * Function-shape (instead of string templates) means:\n * - Optional and multi-param routes can branch on argument presence\n * (`caseNew(templateId?)`).\n * - Query-string composition stays inside the host's resolver, not the\n * view.\n * - TypeScript flags missing arguments at compile time.\n *\n * Mirror sibling: {@link RouterAdapter} owns *navigation primitives*\n * (`push`, `replace`, `pathname`); `BPMRoutes` owns *path strings*. The\n * two compose: views call `router.push(routes.caseDetail(id))`.\n */\nexport interface BPMRoutes {\n /** Workflow dashboard landing. Used by sidebar + dashboard tiles. */\n dashboard(): string;\n /** Inbox (待簽) — pending tasks assigned to the current member. */\n inbox(): string;\n /** Sent (我發起的) — instances the current member initiated. */\n sent(): string;\n /** CC (抄送給我) — instances the current member is copied on. */\n cc(): string;\n /** Cross-view search. */\n search(): string;\n /** Personal delegation rules. */\n delegations(): string;\n /** Notification list. */\n notifications(): string;\n\n /**\n * Detail page for one approval instance.\n *\n * @example default → `/instances/abc123`\n */\n caseDetail(instanceId: string): string;\n /**\n * Launch a new approval instance. When `templateId` is passed, the\n * launch form is pre-populated for that template — by default this is\n * appended as a `?templateId=` query string so the path itself stays\n * stable for routing.\n *\n * @example default `caseNew()` → `/instances/new`\n * @example default `caseNew('tpl-1')` → `/instances/new?templateId=tpl-1`\n */\n caseNew(templateId?: string): string;\n\n /** Template index. */\n templates(): string;\n /** Template designer (xyflow canvas). */\n templateDesigner(templateId: string): string;\n /** Template version history. */\n templateVersions(templateId: string): string;\n /** Template categories admin. */\n templateCategories(): string;\n\n /** Form definitions index. */\n forms(): string;\n /** Form-builder (CodeMirror schema editor + preview). */\n formBuilder(formId: string): string;\n\n /** Per-member notification preferences. */\n notificationSettings(): string;\n\n /** Admin: organization tree management. */\n adminOrgs(): string;\n /** Admin: member directory mapping. */\n adminUsers(): string;\n /** Admin: delegation rule management. */\n adminDelegations(): string;\n}\n\n/**\n * Factory for the default `BPMRoutes` value. Reproduces the exact path\n * literals BPM views used before `BPMRoutesContext` existed, so existing\n * hosts (no provider mounted) keep working unchanged.\n */\nexport function createDefaultBPMRoutes(): BPMRoutes {\n return {\n dashboard: () => '/dashboard',\n inbox: () => '/inbox',\n sent: () => '/sent',\n cc: () => '/cc',\n search: () => '/search',\n delegations: () => '/delegations',\n notifications: () => '/notifications',\n\n caseDetail: (instanceId) => `/instances/${instanceId}`,\n caseNew: (templateId) =>\n templateId\n ? `/instances/new?templateId=${encodeURIComponent(templateId)}`\n : '/instances/new',\n\n templates: () => '/templates',\n templateDesigner: (templateId) => `/templates/${templateId}/designer`,\n templateVersions: (templateId) => `/templates/${templateId}/versions`,\n templateCategories: () => '/templates/categories',\n\n forms: () => '/forms',\n formBuilder: (formId) => `/forms/${formId}/builder`,\n\n notificationSettings: () => '/settings/notifications',\n\n adminOrgs: () => '/admin/orgs',\n adminUsers: () => '/admin/users',\n adminDelegations: () => '/admin/delegations',\n };\n}\n\nconst BPMRoutesContext = createContext<BPMRoutes | null>(null);\n\nexport interface BPMRoutesProviderProps {\n /**\n * Override the path mapping. Provide a full implementation, or spread\n * the default and override individual entries:\n *\n * ```tsx\n * <BPMRoutesProvider value={{\n * ...createDefaultBPMRoutes(),\n * caseDetail: (id) => `/workspace/cases/${id}`,\n * }}>\n * ```\n */\n readonly value?: BPMRoutes;\n readonly children: ReactNode;\n}\n\n/**\n * Wraps the BPM React tree with a {@link BPMRoutes} value. Mounting the\n * provider is **optional** — `useBPMRoutes()` falls back to\n * {@link createDefaultBPMRoutes} when no provider is present. Use it\n * only when the host needs to remap BPM's internal paths.\n */\nexport function BPMRoutesProvider({\n value,\n children,\n}: BPMRoutesProviderProps): React.ReactElement {\n const resolved = useMemo(() => value ?? createDefaultBPMRoutes(), [value]);\n return (\n <BPMRoutesContext.Provider value={resolved}>\n {children}\n </BPMRoutesContext.Provider>\n );\n}\n\n/**\n * Reads the host-configured {@link BPMRoutes}. Falls back to\n * {@link createDefaultBPMRoutes} when no `<BPMRoutesProvider>` ancestor\n * is mounted, so views remain self-contained.\n */\nexport function useBPMRoutes(): BPMRoutes {\n const value = useContext(BPMRoutesContext);\n return value ?? DEFAULT_ROUTES;\n}\n\nconst DEFAULT_ROUTES: BPMRoutes = createDefaultBPMRoutes();\n"],"mappings":";;;;AAqFA,SAAgB,IAAoC;CAClD,OAAO;EACL,iBAAiB;EACjB,aAAa;EACb,YAAY;EACZ,UAAU;EACV,cAAc;EACd,mBAAmB;EACnB,qBAAqB;EAErB,aAAa,MAAe,cAAc;EAC1C,UAAU,MACR,IACI,6BAA6B,mBAAmB,CAAU,MAC1D;EAEN,iBAAiB;EACjB,mBAAmB,MAAe,cAAc,EAAW;EAC3D,mBAAmB,MAAe,cAAc,EAAW;EAC3D,0BAA0B;EAE1B,aAAa;EACb,cAAc,MAAW,UAAU,EAAO;EAE1C,4BAA4B;EAE5B,iBAAiB;EACjB,kBAAkB;EAClB,wBAAwB;CAC1B;AACF;AAEA,IAAM,IAAmB,EAAgC,IAAI;AAwB7D,SAAgB,EAAkB,EAChC,UACA,eAC6C;CAC7C,IAAM,IAAW,QAAc,KAAS,EAAuB,GAAG,CAAC,CAAK,CAAC;CACzE,OACE,kBAAC,EAAiB,UAAlB;EAA2B,OAAO;EAC/B;CACwB,CAAA;AAE/B;AAOA,SAAgB,IAA0B;CAExC,OADc,EAAW,CAClB,KAAS;AAClB;AAEA,IAAM,IAA4B,EAAuB"}
@@ -1,5 +1,5 @@
1
1
  import { ReactElement } from 'react';
2
- import { OrgUnitRecord, PositionRecord } from '../../libs/bpm-core-client/src/lib/organization/index.ts';
2
+ import { OrgUnitRecord, PositionRecord } from '@rytass/bpm-core-client/organization';
3
3
  export type MemberOption = Readonly<{
4
4
  email: string;
5
5
  id: string;
@@ -1,5 +1,5 @@
1
1
  import { ReactElement } from 'react';
2
- import { ApprovalInstanceState, ApprovalInstanceView } from '../../libs/bpm-core-client/src/lib/workflow/index.ts';
2
+ import { ApprovalInstanceState, ApprovalInstanceView } from '@rytass/bpm-core-client/workflow';
3
3
  export interface ApprovalInstanceListPageProps {
4
4
  readonly activeHref: string;
5
5
  readonly defaultState: ApprovalInstanceState | null;
@@ -1,4 +1,4 @@
1
- import { OrgUnitRecord } from '../../libs/bpm-core-client/src/lib/organization/index.ts';
1
+ import { OrgUnitRecord } from '@rytass/bpm-core-client/organization';
2
2
  import { OrgUnitHierarchyDraftChange } from '../lib/org-tree-draft';
3
3
  export type OrgUnitTreeDraftEditorHandle = Readonly<{
4
4
  cancelEditing: () => void;
@@ -1,5 +1,5 @@
1
1
  import { ReactElement, ReactNode } from 'react';
2
- import { ApiMember } from '../../libs/bpm-core-client/src/index.ts';
2
+ import { ApiMember } from '@rytass/bpm-core-client';
3
3
  interface AuthContextValue {
4
4
  readonly loading: boolean;
5
5
  readonly member: ApiMember | null;
@@ -1,4 +1,4 @@
1
- import { OrgUnitRecord } from '../../libs/bpm-core-client/src/lib/organization/index.ts';
1
+ import { OrgUnitRecord } from '@rytass/bpm-core-client/organization';
2
2
  export type OrgUnitParentDraftMap = ReadonlyMap<string, string | null>;
3
3
  export type OrgUnitHierarchyDraftChange = Readonly<{
4
4
  orgUnitId: string;
@@ -32,11 +32,20 @@ export interface BPMRoutes {
32
32
  delegations(): string;
33
33
  /** Notification list. */
34
34
  notifications(): string;
35
- /** Detail page for one approval instance. */
35
+ /**
36
+ * Detail page for one approval instance.
37
+ *
38
+ * @example default → `/instances/abc123`
39
+ */
36
40
  caseDetail(instanceId: string): string;
37
41
  /**
38
42
  * Launch a new approval instance. When `templateId` is passed, the
39
- * launch form is pre-populated for that template.
43
+ * launch form is pre-populated for that template — by default this is
44
+ * appended as a `?templateId=` query string so the path itself stays
45
+ * stable for routing.
46
+ *
47
+ * @example default `caseNew()` → `/instances/new`
48
+ * @example default `caseNew('tpl-1')` → `/instances/new?templateId=tpl-1`
40
49
  */
41
50
  caseNew(templateId?: string): string;
42
51
  /** Template index. */
@@ -1,6 +1,51 @@
1
1
  import { ReactElement, ReactNode } from 'react';
2
- interface BPMNextProvidersProps {
2
+ import { CalendarLocale } from '@mezzanine-ui/react/moment';
3
+ export interface BPMNextProvidersProps {
3
4
  readonly children: ReactNode;
5
+ /**
6
+ * Override the Mezzanine calendar locale. Forwarded to the inner
7
+ * `<Providers>`. Defaults to `CalendarLocale.ZH_TW`.
8
+ */
9
+ readonly locale?: CalendarLocale;
10
+ /**
11
+ * Routes that must remain accessible without a BPM session — visiting
12
+ * these does not redirect to `loginPath` even when `member` is null.
13
+ * Forwarded to `<AuthProvider>`. Defaults to `['/login']`.
14
+ *
15
+ * Hosts that mount BPM under a non-root prefix (see
16
+ * `<BPMRoutesProvider>`) should typically expand this to include their
17
+ * own auth-bypass paths.
18
+ */
19
+ readonly publicPaths?: readonly string[];
20
+ /**
21
+ * Where to redirect unauthenticated users. Forwarded to
22
+ * `<AuthProvider>`. Defaults to `'/login'`. Hosts owning their own
23
+ * login route (the recommended case) override this to their host
24
+ * route, e.g. `'/auth/sign-in'`.
25
+ */
26
+ readonly loginPath?: string;
4
27
  }
5
- export declare function BPMNextProviders({ children, }: BPMNextProvidersProps): ReactElement;
6
- export {};
28
+ /**
29
+ * One-line Next.js App Router shim for the full BPM provider stack.
30
+ * Mounts in the host's root layout (or layout for the BPM sub-tree):
31
+ *
32
+ * ```tsx
33
+ * import { BPMNextProviders } from '@rytass/bpm-core-react/next';
34
+ *
35
+ * export default function RootLayout({ children }) {
36
+ * return (
37
+ * <html><body>
38
+ * <BPMNextProviders loginPath="/auth/sign-in">
39
+ * {children}
40
+ * </BPMNextProviders>
41
+ * </body></html>
42
+ * );
43
+ * }
44
+ * ```
45
+ *
46
+ * Forwards every prop on {@link BPMNextProvidersProps} to the inner
47
+ * `<Providers>` and `<AuthProvider>`. For per-feature path remapping
48
+ * (BPM internal navigation), additionally wrap with
49
+ * `<BPMRoutesProvider>` exported from the same subpath.
50
+ */
51
+ export declare function BPMNextProviders(props: BPMNextProvidersProps): ReactElement;
@@ -1,2 +1,2 @@
1
- "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../chunks/routes-config-2aKbWq2H.cjs");let t=require("react"),n=require("react/jsx-runtime"),r=require("next/navigation"),i=require("@rytass/bpm-core-react");function a({children:e}){let a=(0,r.useRouter)(),o=(0,r.usePathname)(),s=(0,r.useSearchParams)();return(0,n.jsx)(i.RouterAdapterProvider,{value:(0,t.useMemo)(()=>({pathname:o,push:e=>a.push(e),replace:e=>a.replace(e),back:()=>a.back(),searchParams:()=>new URLSearchParams(s?.toString()??``)}),[a,o,s]),children:(0,n.jsx)(i.Providers,{children:e})})}function o({children:e}){return(0,n.jsx)(t.Suspense,{fallback:null,children:(0,n.jsx)(a,{children:e})})}exports.BPMNextProviders=o,exports.BPMRoutesProvider=e.t,exports.createDefaultBPMRoutes=e.n,exports.useBPMRoutes=e.r;
1
+ "use client";Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../chunks/routes-config-2aKbWq2H.cjs");let t=require("react"),n=require("react/jsx-runtime"),r=require("next/navigation"),i=require("@rytass/bpm-core-react");function a({children:e,locale:a,publicPaths:o,loginPath:s}){let c=(0,r.useRouter)(),l=(0,r.usePathname)(),u=(0,r.useSearchParams)();return(0,n.jsx)(i.RouterAdapterProvider,{value:(0,t.useMemo)(()=>({pathname:l,push:e=>c.push(e),replace:e=>c.replace(e),back:()=>c.back(),searchParams:()=>new URLSearchParams(u?.toString()??``)}),[c,l,u]),children:(0,n.jsx)(i.Providers,{locale:a,publicPaths:o,loginPath:s,children:e})})}function o(e){return(0,n.jsx)(t.Suspense,{fallback:null,children:(0,n.jsx)(a,{...e})})}exports.BPMNextProviders=o,exports.BPMRoutesProvider=e.t,exports.createDefaultBPMRoutes=e.n,exports.useBPMRoutes=e.r;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../src/next/BPMNextProviders.tsx"],"sourcesContent":["'use client';\n\n// One-line Next.js App Router shim for BPM. Reads `next/navigation` hooks,\n// builds a `RouterAdapter`, then composes `<RouterAdapterProvider>` and the\n// shared `<BPMProviders>`. Wrapped in `<Suspense>` so static prerender of\n// routes like `/404` does not fail on `useSearchParams()` during `next build`.\n\nimport { Suspense, useMemo, type ReactElement, type ReactNode } from 'react';\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation';\nimport {\n Providers as BPMProviders,\n RouterAdapterProvider,\n type RouterAdapter,\n} from '@rytass/bpm-core-react';\n\ninterface BPMNextProvidersProps {\n readonly children: ReactNode;\n}\n\nfunction BPMNextProvidersBody({\n children,\n}: BPMNextProvidersProps): ReactElement {\n const nextRouter = useRouter();\n const pathname = usePathname();\n const searchParams = useSearchParams();\n\n const adapter = useMemo<RouterAdapter>(\n () => ({\n pathname,\n push: (href: string): void => nextRouter.push(href),\n replace: (href: string): void => nextRouter.replace(href),\n back: (): void => nextRouter.back(),\n searchParams: (): URLSearchParams =>\n new URLSearchParams(searchParams?.toString() ?? ''),\n }),\n [nextRouter, pathname, searchParams],\n );\n\n return (\n <RouterAdapterProvider value={adapter}>\n <BPMProviders>{children}</BPMProviders>\n </RouterAdapterProvider>\n );\n}\n\nexport function BPMNextProviders({\n children,\n}: BPMNextProvidersProps): ReactElement {\n return (\n <Suspense fallback={null}>\n <BPMNextProvidersBody>{children}</BPMNextProvidersBody>\n </Suspense>\n );\n}\n"],"mappings":"+PAmBA,SAAS,EAAqB,CAC5B,YACsC,CACtC,IAAM,GAAA,EAAA,EAAA,WAAuB,EACvB,GAAA,EAAA,EAAA,aAAuB,EACvB,GAAA,EAAA,EAAA,iBAA+B,EAcrC,OACE,EAAA,EAAA,KAAC,EAAA,sBAAD,CAAuB,OAAA,EAAA,EAAA,cAZhB,CACL,WACA,KAAO,GAAuB,EAAW,KAAK,CAAI,EAClD,QAAU,GAAuB,EAAW,QAAQ,CAAI,EACxD,SAAkB,EAAW,KAAK,EAClC,iBACE,IAAI,gBAAgB,GAAc,SAAS,GAAK,EAAE,CACtD,GACA,CAAC,EAAY,EAAU,CAAY,CAIL,YAC5B,EAAA,EAAA,KAAC,EAAA,UAAD,CAAe,UAAuB,CAAA,CACjB,CAAA,CAE3B,CAEA,SAAgB,EAAiB,CAC/B,YACsC,CACtC,OACE,EAAA,EAAA,KAAC,EAAA,SAAD,CAAU,SAAU,eAClB,EAAA,EAAA,KAAC,EAAD,CAAuB,UAA+B,CAAA,CAC9C,CAAA,CAEd"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../src/next/BPMNextProviders.tsx"],"sourcesContent":["'use client';\n\n// One-line Next.js App Router shim for BPM. Reads `next/navigation` hooks,\n// builds a `RouterAdapter`, then composes `<RouterAdapterProvider>` and the\n// shared `<BPMProviders>`. Wrapped in `<Suspense>` so static prerender of\n// routes like `/404` does not fail on `useSearchParams()` during `next build`.\n\nimport { Suspense, useMemo, type ReactElement, type ReactNode } from 'react';\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation';\nimport {\n Providers as BPMProviders,\n RouterAdapterProvider,\n type RouterAdapter,\n} from '@rytass/bpm-core-react';\nimport type { CalendarLocale } from '@mezzanine-ui/react/moment';\n\nexport interface BPMNextProvidersProps {\n readonly children: ReactNode;\n /**\n * Override the Mezzanine calendar locale. Forwarded to the inner\n * `<Providers>`. Defaults to `CalendarLocale.ZH_TW`.\n */\n readonly locale?: CalendarLocale;\n /**\n * Routes that must remain accessible without a BPM session — visiting\n * these does not redirect to `loginPath` even when `member` is null.\n * Forwarded to `<AuthProvider>`. Defaults to `['/login']`.\n *\n * Hosts that mount BPM under a non-root prefix (see\n * `<BPMRoutesProvider>`) should typically expand this to include their\n * own auth-bypass paths.\n */\n readonly publicPaths?: readonly string[];\n /**\n * Where to redirect unauthenticated users. Forwarded to\n * `<AuthProvider>`. Defaults to `'/login'`. Hosts owning their own\n * login route (the recommended case) override this to their host\n * route, e.g. `'/auth/sign-in'`.\n */\n readonly loginPath?: string;\n}\n\nfunction BPMNextProvidersBody({\n children,\n locale,\n publicPaths,\n loginPath,\n}: BPMNextProvidersProps): ReactElement {\n const nextRouter = useRouter();\n const pathname = usePathname();\n const searchParams = useSearchParams();\n\n const adapter = useMemo<RouterAdapter>(\n () => ({\n pathname,\n push: (href: string): void => nextRouter.push(href),\n replace: (href: string): void => nextRouter.replace(href),\n back: (): void => nextRouter.back(),\n searchParams: (): URLSearchParams =>\n new URLSearchParams(searchParams?.toString() ?? ''),\n }),\n [nextRouter, pathname, searchParams],\n );\n\n return (\n <RouterAdapterProvider value={adapter}>\n <BPMProviders\n locale={locale}\n publicPaths={publicPaths}\n loginPath={loginPath}\n >\n {children}\n </BPMProviders>\n </RouterAdapterProvider>\n );\n}\n\n/**\n * One-line Next.js App Router shim for the full BPM provider stack.\n * Mounts in the host's root layout (or layout for the BPM sub-tree):\n *\n * ```tsx\n * import { BPMNextProviders } from '@rytass/bpm-core-react/next';\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html><body>\n * <BPMNextProviders loginPath=\"/auth/sign-in\">\n * {children}\n * </BPMNextProviders>\n * </body></html>\n * );\n * }\n * ```\n *\n * Forwards every prop on {@link BPMNextProvidersProps} to the inner\n * `<Providers>` and `<AuthProvider>`. For per-feature path remapping\n * (BPM internal navigation), additionally wrap with\n * `<BPMRoutesProvider>` exported from the same subpath.\n */\nexport function BPMNextProviders(props: BPMNextProvidersProps): ReactElement {\n return (\n <Suspense fallback={null}>\n <BPMNextProvidersBody {...props} />\n </Suspense>\n );\n}\n"],"mappings":"+PA0CA,SAAS,EAAqB,CAC5B,WACA,SACA,cACA,aACsC,CACtC,IAAM,GAAA,EAAA,EAAA,WAAuB,EACvB,GAAA,EAAA,EAAA,aAAuB,EACvB,GAAA,EAAA,EAAA,iBAA+B,EAcrC,OACE,EAAA,EAAA,KAAC,EAAA,sBAAD,CAAuB,OAAA,EAAA,EAAA,cAZhB,CACL,WACA,KAAO,GAAuB,EAAW,KAAK,CAAI,EAClD,QAAU,GAAuB,EAAW,QAAQ,CAAI,EACxD,SAAkB,EAAW,KAAK,EAClC,iBACE,IAAI,gBAAgB,GAAc,SAAS,GAAK,EAAE,CACtD,GACA,CAAC,EAAY,EAAU,CAAY,CAIL,YAC5B,EAAA,EAAA,KAAC,EAAA,UAAD,CACU,SACK,cACF,YAEV,UACW,CAAA,CACO,CAAA,CAE3B,CAyBA,SAAgB,EAAiB,EAA4C,CAC3E,OACE,EAAA,EAAA,KAAC,EAAA,SAAD,CAAU,SAAU,eAClB,EAAA,EAAA,KAAC,EAAD,CAAsB,GAAI,CAAQ,CAAA,CAC1B,CAAA,CAEd"}
@@ -5,27 +5,32 @@ import { jsx as a } from "react/jsx-runtime";
5
5
  import { usePathname as o, useRouter as s, useSearchParams as c } from "next/navigation";
6
6
  import { Providers as l, RouterAdapterProvider as u } from "@rytass/bpm-core-react";
7
7
  //#region src/next/BPMNextProviders.tsx
8
- function d({ children: e }) {
9
- let t = s(), n = o(), r = c();
8
+ function d({ children: e, locale: t, publicPaths: n, loginPath: r }) {
9
+ let d = s(), f = o(), p = c();
10
10
  return /* @__PURE__ */ a(u, {
11
11
  value: i(() => ({
12
- pathname: n,
13
- push: (e) => t.push(e),
14
- replace: (e) => t.replace(e),
15
- back: () => t.back(),
16
- searchParams: () => new URLSearchParams(r?.toString() ?? "")
12
+ pathname: f,
13
+ push: (e) => d.push(e),
14
+ replace: (e) => d.replace(e),
15
+ back: () => d.back(),
16
+ searchParams: () => new URLSearchParams(p?.toString() ?? "")
17
17
  }), [
18
- t,
19
- n,
20
- r
18
+ d,
19
+ f,
20
+ p
21
21
  ]),
22
- children: /* @__PURE__ */ a(l, { children: e })
22
+ children: /* @__PURE__ */ a(l, {
23
+ locale: t,
24
+ publicPaths: n,
25
+ loginPath: r,
26
+ children: e
27
+ })
23
28
  });
24
29
  }
25
- function f({ children: e }) {
30
+ function f(e) {
26
31
  return /* @__PURE__ */ a(r, {
27
32
  fallback: null,
28
- children: /* @__PURE__ */ a(d, { children: e })
33
+ children: /* @__PURE__ */ a(d, { ...e })
29
34
  });
30
35
  }
31
36
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/next/BPMNextProviders.tsx"],"sourcesContent":["'use client';\n\n// One-line Next.js App Router shim for BPM. Reads `next/navigation` hooks,\n// builds a `RouterAdapter`, then composes `<RouterAdapterProvider>` and the\n// shared `<BPMProviders>`. Wrapped in `<Suspense>` so static prerender of\n// routes like `/404` does not fail on `useSearchParams()` during `next build`.\n\nimport { Suspense, useMemo, type ReactElement, type ReactNode } from 'react';\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation';\nimport {\n Providers as BPMProviders,\n RouterAdapterProvider,\n type RouterAdapter,\n} from '@rytass/bpm-core-react';\n\ninterface BPMNextProvidersProps {\n readonly children: ReactNode;\n}\n\nfunction BPMNextProvidersBody({\n children,\n}: BPMNextProvidersProps): ReactElement {\n const nextRouter = useRouter();\n const pathname = usePathname();\n const searchParams = useSearchParams();\n\n const adapter = useMemo<RouterAdapter>(\n () => ({\n pathname,\n push: (href: string): void => nextRouter.push(href),\n replace: (href: string): void => nextRouter.replace(href),\n back: (): void => nextRouter.back(),\n searchParams: (): URLSearchParams =>\n new URLSearchParams(searchParams?.toString() ?? ''),\n }),\n [nextRouter, pathname, searchParams],\n );\n\n return (\n <RouterAdapterProvider value={adapter}>\n <BPMProviders>{children}</BPMProviders>\n </RouterAdapterProvider>\n );\n}\n\nexport function BPMNextProviders({\n children,\n}: BPMNextProvidersProps): ReactElement {\n return (\n <Suspense fallback={null}>\n <BPMNextProvidersBody>{children}</BPMNextProvidersBody>\n </Suspense>\n );\n}\n"],"mappings":";;;;;;;AAmBA,SAAS,EAAqB,EAC5B,eACsC;CACtC,IAAM,IAAa,EAAU,GACvB,IAAW,EAAY,GACvB,IAAe,EAAgB;CAcrC,OACE,kBAAC,GAAD;EAAuB,OAbT,SACP;GACL;GACA,OAAO,MAAuB,EAAW,KAAK,CAAI;GAClD,UAAU,MAAuB,EAAW,QAAQ,CAAI;GACxD,YAAkB,EAAW,KAAK;GAClC,oBACE,IAAI,gBAAgB,GAAc,SAAS,KAAK,EAAE;EACtD,IACA;GAAC;GAAY;GAAU;EAAY,CAIL;YAC5B,kBAAC,GAAD,EAAe,YAAuB,CAAA;CACjB,CAAA;AAE3B;AAEA,SAAgB,EAAiB,EAC/B,eACsC;CACtC,OACE,kBAAC,GAAD;EAAU,UAAU;YAClB,kBAAC,GAAD,EAAuB,YAA+B,CAAA;CAC9C,CAAA;AAEd"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/next/BPMNextProviders.tsx"],"sourcesContent":["'use client';\n\n// One-line Next.js App Router shim for BPM. Reads `next/navigation` hooks,\n// builds a `RouterAdapter`, then composes `<RouterAdapterProvider>` and the\n// shared `<BPMProviders>`. Wrapped in `<Suspense>` so static prerender of\n// routes like `/404` does not fail on `useSearchParams()` during `next build`.\n\nimport { Suspense, useMemo, type ReactElement, type ReactNode } from 'react';\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation';\nimport {\n Providers as BPMProviders,\n RouterAdapterProvider,\n type RouterAdapter,\n} from '@rytass/bpm-core-react';\nimport type { CalendarLocale } from '@mezzanine-ui/react/moment';\n\nexport interface BPMNextProvidersProps {\n readonly children: ReactNode;\n /**\n * Override the Mezzanine calendar locale. Forwarded to the inner\n * `<Providers>`. Defaults to `CalendarLocale.ZH_TW`.\n */\n readonly locale?: CalendarLocale;\n /**\n * Routes that must remain accessible without a BPM session — visiting\n * these does not redirect to `loginPath` even when `member` is null.\n * Forwarded to `<AuthProvider>`. Defaults to `['/login']`.\n *\n * Hosts that mount BPM under a non-root prefix (see\n * `<BPMRoutesProvider>`) should typically expand this to include their\n * own auth-bypass paths.\n */\n readonly publicPaths?: readonly string[];\n /**\n * Where to redirect unauthenticated users. Forwarded to\n * `<AuthProvider>`. Defaults to `'/login'`. Hosts owning their own\n * login route (the recommended case) override this to their host\n * route, e.g. `'/auth/sign-in'`.\n */\n readonly loginPath?: string;\n}\n\nfunction BPMNextProvidersBody({\n children,\n locale,\n publicPaths,\n loginPath,\n}: BPMNextProvidersProps): ReactElement {\n const nextRouter = useRouter();\n const pathname = usePathname();\n const searchParams = useSearchParams();\n\n const adapter = useMemo<RouterAdapter>(\n () => ({\n pathname,\n push: (href: string): void => nextRouter.push(href),\n replace: (href: string): void => nextRouter.replace(href),\n back: (): void => nextRouter.back(),\n searchParams: (): URLSearchParams =>\n new URLSearchParams(searchParams?.toString() ?? ''),\n }),\n [nextRouter, pathname, searchParams],\n );\n\n return (\n <RouterAdapterProvider value={adapter}>\n <BPMProviders\n locale={locale}\n publicPaths={publicPaths}\n loginPath={loginPath}\n >\n {children}\n </BPMProviders>\n </RouterAdapterProvider>\n );\n}\n\n/**\n * One-line Next.js App Router shim for the full BPM provider stack.\n * Mounts in the host's root layout (or layout for the BPM sub-tree):\n *\n * ```tsx\n * import { BPMNextProviders } from '@rytass/bpm-core-react/next';\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html><body>\n * <BPMNextProviders loginPath=\"/auth/sign-in\">\n * {children}\n * </BPMNextProviders>\n * </body></html>\n * );\n * }\n * ```\n *\n * Forwards every prop on {@link BPMNextProvidersProps} to the inner\n * `<Providers>` and `<AuthProvider>`. For per-feature path remapping\n * (BPM internal navigation), additionally wrap with\n * `<BPMRoutesProvider>` exported from the same subpath.\n */\nexport function BPMNextProviders(props: BPMNextProvidersProps): ReactElement {\n return (\n <Suspense fallback={null}>\n <BPMNextProvidersBody {...props} />\n </Suspense>\n );\n}\n"],"mappings":";;;;;;;AA0CA,SAAS,EAAqB,EAC5B,aACA,WACA,gBACA,gBACsC;CACtC,IAAM,IAAa,EAAU,GACvB,IAAW,EAAY,GACvB,IAAe,EAAgB;CAcrC,OACE,kBAAC,GAAD;EAAuB,OAbT,SACP;GACL;GACA,OAAO,MAAuB,EAAW,KAAK,CAAI;GAClD,UAAU,MAAuB,EAAW,QAAQ,CAAI;GACxD,YAAkB,EAAW,KAAK;GAClC,oBACE,IAAI,gBAAgB,GAAc,SAAS,KAAK,EAAE;EACtD,IACA;GAAC;GAAY;GAAU;EAAY,CAIL;YAC5B,kBAAC,GAAD;GACU;GACK;GACF;GAEV;EACW,CAAA;CACO,CAAA;AAE3B;AAyBA,SAAgB,EAAiB,GAA4C;CAC3E,OACE,kBAAC,GAAD;EAAU,UAAU;YAClB,kBAAC,GAAD,EAAsB,GAAI,EAAQ,CAAA;CAC1B,CAAA;AAEd"}
@@ -1,6 +1,6 @@
1
1
  import { CSSProperties, ReactElement } from 'react';
2
- import { FormDefinitionSchema, FormFieldDefinition, FormUiSchema } from '../../../../libs/shared/src/lib/form.ts';
3
- import { FormRendererValues } from '../../../../libs/bpm-core-client/src/lib/form/index.ts';
2
+ import { FormDefinitionSchema, FormFieldDefinition, FormUiSchema } from '@rytass/bpm-core-shared/form';
3
+ import { FormRendererValues } from '@rytass/bpm-core-client/form';
4
4
  export interface FormRendererProps {
5
5
  readonly emptyText?: string;
6
6
  readonly errors?: Readonly<Record<string, string>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rytass/bpm-core-react",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "BPM approval workflow React components and views for the Rytass BPM stack. Self-contained AuthProvider, NotificationDrawer, AppNavigation, plus full views for inbox / instances / templates / forms / admin / settings that compose on top of Mezzanine UI and the BPM client functions.",
5
5
  "keywords": [
6
6
  "bpm",
@@ -278,8 +278,8 @@
278
278
  }
279
279
  },
280
280
  "peerDependencies": {
281
- "@rytass/bpm-core-client": "^0.1.5",
282
- "@rytass/bpm-core-shared": "^0.1.5",
281
+ "@rytass/bpm-core-client": "^0.1.7",
282
+ "@rytass/bpm-core-shared": "^0.1.7",
283
283
  "@mezzanine-ui/react": "^1.1.0",
284
284
  "@mezzanine-ui/icons": "^1.0.2",
285
285
  "react": "^18.0.0 || ^19.0.0",