@entifix/next-shell 0.1.0-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/back-office/account-menu.d.ts +29 -0
- package/dist/lib/back-office/account-menu.d.ts.map +1 -0
- package/dist/lib/back-office/account-menu.js +70 -0
- package/dist/lib/back-office/account-menu.js.map +1 -0
- package/dist/lib/back-office/back-office-shell.d.ts +50 -0
- package/dist/lib/back-office/back-office-shell.d.ts.map +1 -0
- package/dist/lib/back-office/back-office-shell.js +128 -0
- package/dist/lib/back-office/back-office-shell.js.map +1 -0
- package/dist/lib/back-office/breadcrumbs.d.ts +16 -0
- package/dist/lib/back-office/breadcrumbs.d.ts.map +1 -0
- package/dist/lib/back-office/breadcrumbs.js +53 -0
- package/dist/lib/back-office/breadcrumbs.js.map +1 -0
- package/dist/lib/back-office/group-by-screen-type.d.ts +21 -0
- package/dist/lib/back-office/group-by-screen-type.d.ts.map +1 -0
- package/dist/lib/back-office/group-by-screen-type.js +39 -0
- package/dist/lib/back-office/group-by-screen-type.js.map +1 -0
- package/dist/lib/back-office/index.d.ts +6 -0
- package/dist/lib/back-office/index.d.ts.map +1 -0
- package/dist/lib/back-office/index.js +7 -0
- package/dist/lib/back-office/index.js.map +1 -0
- package/dist/lib/back-office/nav.d.ts +39 -0
- package/dist/lib/back-office/nav.d.ts.map +1 -0
- package/dist/lib/back-office/nav.js +3 -0
- package/dist/lib/back-office/nav.js.map +1 -0
- package/dist/lib/back-office/sidebar-nav.d.ts +26 -0
- package/dist/lib/back-office/sidebar-nav.d.ts.map +1 -0
- package/dist/lib/back-office/sidebar-nav.js +181 -0
- package/dist/lib/back-office/sidebar-nav.js.map +1 -0
- package/dist/lib/command-palette/command-palette-host.d.ts +41 -0
- package/dist/lib/command-palette/command-palette-host.d.ts.map +1 -0
- package/dist/lib/command-palette/command-palette-host.js +196 -0
- package/dist/lib/command-palette/command-palette-host.js.map +1 -0
- package/dist/lib/command-palette/index.d.ts +9 -0
- package/dist/lib/command-palette/index.d.ts.map +1 -0
- package/dist/lib/command-palette/index.js +10 -0
- package/dist/lib/command-palette/index.js.map +1 -0
- package/dist/lib/command-palette/palette-command.d.ts +32 -0
- package/dist/lib/command-palette/palette-command.d.ts.map +1 -0
- package/dist/lib/command-palette/palette-command.js +19 -0
- package/dist/lib/command-palette/palette-command.js.map +1 -0
- package/dist/lib/command-palette/use-command-recency.d.ts +28 -0
- package/dist/lib/command-palette/use-command-recency.d.ts.map +1 -0
- package/dist/lib/command-palette/use-command-recency.js +67 -0
- package/dist/lib/command-palette/use-command-recency.js.map +1 -0
- package/dist/lib/command-palette/use-command-source.d.ts +17 -0
- package/dist/lib/command-palette/use-command-source.d.ts.map +1 -0
- package/dist/lib/command-palette/use-command-source.js +70 -0
- package/dist/lib/command-palette/use-command-source.js.map +1 -0
- package/dist/lib/command-palette/use-nav-source.d.ts +21 -0
- package/dist/lib/command-palette/use-nav-source.d.ts.map +1 -0
- package/dist/lib/command-palette/use-nav-source.js +78 -0
- package/dist/lib/command-palette/use-nav-source.js.map +1 -0
- package/dist/lib/command-palette/use-records-source.d.ts +23 -0
- package/dist/lib/command-palette/use-records-source.d.ts.map +1 -0
- package/dist/lib/command-palette/use-records-source.js +199 -0
- package/dist/lib/command-palette/use-records-source.js.map +1 -0
- package/dist/lib/command-palette/use-tabs-source.d.ts +20 -0
- package/dist/lib/command-palette/use-tabs-source.d.ts.map +1 -0
- package/dist/lib/command-palette/use-tabs-source.js +52 -0
- package/dist/lib/command-palette/use-tabs-source.js.map +1 -0
- package/dist/lib/command-palette/use-use-cases-source.d.ts +22 -0
- package/dist/lib/command-palette/use-use-cases-source.d.ts.map +1 -0
- package/dist/lib/command-palette/use-use-cases-source.js +93 -0
- package/dist/lib/command-palette/use-use-cases-source.js.map +1 -0
- package/dist/lib/config/config-route.d.ts +51 -0
- package/dist/lib/config/config-route.d.ts.map +1 -0
- package/dist/lib/config/config-route.js +65 -0
- package/dist/lib/config/config-route.js.map +1 -0
- package/dist/lib/config/service-proxy-route.d.ts +28 -0
- package/dist/lib/config/service-proxy-route.d.ts.map +1 -0
- package/dist/lib/config/service-proxy-route.js +125 -0
- package/dist/lib/config/service-proxy-route.js.map +1 -0
- package/dist/lib/config/service-token.d.ts +5 -0
- package/dist/lib/config/service-token.d.ts.map +1 -0
- package/dist/lib/config/service-token.js +18 -0
- package/dist/lib/config/service-token.js.map +1 -0
- package/dist/lib/crud/entity-crud-form.d.ts +49 -0
- package/dist/lib/crud/entity-crud-form.d.ts.map +1 -0
- package/dist/lib/crud/entity-crud-form.js +133 -0
- package/dist/lib/crud/entity-crud-form.js.map +1 -0
- package/dist/lib/crud/hand-off-write.d.ts +35 -0
- package/dist/lib/crud/hand-off-write.d.ts.map +1 -0
- package/dist/lib/crud/hand-off-write.js +27 -0
- package/dist/lib/crud/hand-off-write.js.map +1 -0
- package/dist/lib/crud/index.d.ts +9 -0
- package/dist/lib/crud/index.d.ts.map +1 -0
- package/dist/lib/crud/index.js +10 -0
- package/dist/lib/crud/index.js.map +1 -0
- package/dist/lib/crud/make-entity-crud.d.ts +28 -0
- package/dist/lib/crud/make-entity-crud.d.ts.map +1 -0
- package/dist/lib/crud/make-entity-crud.js +318 -0
- package/dist/lib/crud/make-entity-crud.js.map +1 -0
- package/dist/lib/crud/make-entity-crud.types.d.ts +237 -0
- package/dist/lib/crud/make-entity-crud.types.d.ts.map +1 -0
- package/dist/lib/crud/make-entity-crud.types.js +6 -0
- package/dist/lib/crud/make-entity-crud.types.js.map +1 -0
- package/dist/lib/crud/pending-notice.d.ts +31 -0
- package/dist/lib/crud/pending-notice.d.ts.map +1 -0
- package/dist/lib/crud/pending-notice.js +72 -0
- package/dist/lib/crud/pending-notice.js.map +1 -0
- package/dist/lib/crud/slug.d.ts +13 -0
- package/dist/lib/crud/slug.d.ts.map +1 -0
- package/dist/lib/crud/slug.js +13 -0
- package/dist/lib/crud/slug.js.map +1 -0
- package/dist/lib/crud/use-entity-affordances.d.ts +20 -0
- package/dist/lib/crud/use-entity-affordances.d.ts.map +1 -0
- package/dist/lib/crud/use-entity-affordances.js +22 -0
- package/dist/lib/crud/use-entity-affordances.js.map +1 -0
- package/dist/lib/crud/use-entity-bulk.d.ts +43 -0
- package/dist/lib/crud/use-entity-bulk.d.ts.map +1 -0
- package/dist/lib/crud/use-entity-bulk.js +106 -0
- package/dist/lib/crud/use-entity-bulk.js.map +1 -0
- package/dist/lib/crud/use-entity-link-sources.d.ts +25 -0
- package/dist/lib/crud/use-entity-link-sources.d.ts.map +1 -0
- package/dist/lib/crud/use-entity-link-sources.js +37 -0
- package/dist/lib/crud/use-entity-link-sources.js.map +1 -0
- package/dist/lib/health/health-routes.d.ts +37 -0
- package/dist/lib/health/health-routes.d.ts.map +1 -0
- package/dist/lib/health/health-routes.js +90 -0
- package/dist/lib/health/health-routes.js.map +1 -0
- package/dist/lib/i18n/catalog/en.d.ts +4 -0
- package/dist/lib/i18n/catalog/en.d.ts.map +1 -0
- package/dist/lib/i18n/catalog/en.js +347 -0
- package/dist/lib/i18n/catalog/en.js.map +1 -0
- package/dist/lib/i18n/catalog/es.d.ts +397 -0
- package/dist/lib/i18n/catalog/es.d.ts.map +1 -0
- package/dist/lib/i18n/catalog/es.js +407 -0
- package/dist/lib/i18n/catalog/es.js.map +1 -0
- package/dist/lib/i18n/catalog/index.d.ts +671 -0
- package/dist/lib/i18n/catalog/index.d.ts.map +1 -0
- package/dist/lib/i18n/catalog/index.js +28 -0
- package/dist/lib/i18n/catalog/index.js.map +1 -0
- package/dist/lib/i18n/index.d.ts +2 -0
- package/dist/lib/i18n/index.d.ts.map +1 -0
- package/dist/lib/i18n/index.js +3 -0
- package/dist/lib/i18n/index.js.map +1 -0
- package/dist/lib/i18n/locale-link.d.ts +23 -0
- package/dist/lib/i18n/locale-link.d.ts.map +1 -0
- package/dist/lib/i18n/locale-link.js +43 -0
- package/dist/lib/i18n/locale-link.js.map +1 -0
- package/dist/lib/i18n/spec-catalog.d.ts +2 -0
- package/dist/lib/i18n/spec-catalog.d.ts.map +1 -0
- package/dist/lib/i18n/spec-catalog.js +84 -0
- package/dist/lib/i18n/spec-catalog.js.map +1 -0
- package/dist/lib/search/record-search-route.d.ts +44 -0
- package/dist/lib/search/record-search-route.d.ts.map +1 -0
- package/dist/lib/search/record-search-route.js +158 -0
- package/dist/lib/search/record-search-route.js.map +1 -0
- package/dist/lib/search/record-search-source.d.ts +59 -0
- package/dist/lib/search/record-search-source.d.ts.map +1 -0
- package/dist/lib/search/record-search-source.js +118 -0
- package/dist/lib/search/record-search-source.js.map +1 -0
- package/dist/lib/search/record-search.types.d.ts +85 -0
- package/dist/lib/search/record-search.types.d.ts.map +1 -0
- package/dist/lib/search/record-search.types.js +29 -0
- package/dist/lib/search/record-search.types.js.map +1 -0
- package/dist/lib/search/search-records.d.ts +25 -0
- package/dist/lib/search/search-records.d.ts.map +1 -0
- package/dist/lib/search/search-records.js +36 -0
- package/dist/lib/search/search-records.js.map +1 -0
- package/dist/lib/session/account-links.d.ts +46 -0
- package/dist/lib/session/account-links.d.ts.map +1 -0
- package/dist/lib/session/account-links.js +41 -0
- package/dist/lib/session/account-links.js.map +1 -0
- package/dist/lib/session/bearer.d.ts +25 -0
- package/dist/lib/session/bearer.d.ts.map +1 -0
- package/dist/lib/session/bearer.js +31 -0
- package/dist/lib/session/bearer.js.map +1 -0
- package/dist/lib/session/cookies.d.ts +14 -0
- package/dist/lib/session/cookies.d.ts.map +1 -0
- package/dist/lib/session/cookies.js +33 -0
- package/dist/lib/session/cookies.js.map +1 -0
- package/dist/lib/session/device.d.ts +31 -0
- package/dist/lib/session/device.d.ts.map +1 -0
- package/dist/lib/session/device.js +80 -0
- package/dist/lib/session/device.js.map +1 -0
- package/dist/lib/session/index.d.ts +3 -0
- package/dist/lib/session/index.d.ts.map +1 -0
- package/dist/lib/session/index.js +12 -0
- package/dist/lib/session/index.js.map +1 -0
- package/dist/lib/session/refresh-route.d.ts +19 -0
- package/dist/lib/session/refresh-route.d.ts.map +1 -0
- package/dist/lib/session/refresh-route.js +85 -0
- package/dist/lib/session/refresh-route.js.map +1 -0
- package/dist/lib/session/session-keepalive.d.ts +52 -0
- package/dist/lib/session/session-keepalive.d.ts.map +1 -0
- package/dist/lib/session/session-keepalive.js +72 -0
- package/dist/lib/session/session-keepalive.js.map +1 -0
- package/dist/lib/session/use-session-refresh.d.ts +43 -0
- package/dist/lib/session/use-session-refresh.d.ts.map +1 -0
- package/dist/lib/session/use-session-refresh.js +120 -0
- package/dist/lib/session/use-session-refresh.js.map +1 -0
- package/dist/lib/wizard/index.d.ts +4 -0
- package/dist/lib/wizard/index.d.ts.map +1 -0
- package/dist/lib/wizard/index.js +5 -0
- package/dist/lib/wizard/index.js.map +1 -0
- package/dist/lib/wizard/use-wizard-draft.d.ts +22 -0
- package/dist/lib/wizard/use-wizard-draft.d.ts.map +1 -0
- package/dist/lib/wizard/use-wizard-draft.js +39 -0
- package/dist/lib/wizard/use-wizard-draft.js.map +1 -0
- package/dist/lib/wizard/use-wizard-step-param.d.ts +60 -0
- package/dist/lib/wizard/use-wizard-step-param.d.ts.map +1 -0
- package/dist/lib/wizard/use-wizard-step-param.js +94 -0
- package/dist/lib/wizard/use-wizard-step-param.js.map +1 -0
- package/dist/lib/wizard/wizard-tab-kind.d.ts +31 -0
- package/dist/lib/wizard/wizard-tab-kind.d.ts.map +1 -0
- package/dist/lib/wizard/wizard-tab-kind.js +33 -0
- package/dist/lib/wizard/wizard-tab-kind.js.map +1 -0
- package/dist/lib/workspace/drafts-state.d.ts +88 -0
- package/dist/lib/workspace/drafts-state.d.ts.map +1 -0
- package/dist/lib/workspace/drafts-state.js +128 -0
- package/dist/lib/workspace/drafts-state.js.map +1 -0
- package/dist/lib/workspace/entity-nav.d.ts +26 -0
- package/dist/lib/workspace/entity-nav.d.ts.map +1 -0
- package/dist/lib/workspace/entity-nav.js +56 -0
- package/dist/lib/workspace/entity-nav.js.map +1 -0
- package/dist/lib/workspace/entity-tab-kind.d.ts +51 -0
- package/dist/lib/workspace/entity-tab-kind.d.ts.map +1 -0
- package/dist/lib/workspace/entity-tab-kind.js +47 -0
- package/dist/lib/workspace/entity-tab-kind.js.map +1 -0
- package/dist/lib/workspace/idb-state-storage.d.ts +9 -0
- package/dist/lib/workspace/idb-state-storage.d.ts.map +1 -0
- package/dist/lib/workspace/idb-state-storage.js +32 -0
- package/dist/lib/workspace/idb-state-storage.js.map +1 -0
- package/dist/lib/workspace/index.d.ts +13 -0
- package/dist/lib/workspace/index.d.ts.map +1 -0
- package/dist/lib/workspace/index.js +14 -0
- package/dist/lib/workspace/index.js.map +1 -0
- package/dist/lib/workspace/pending-state.d.ts +84 -0
- package/dist/lib/workspace/pending-state.d.ts.map +1 -0
- package/dist/lib/workspace/pending-state.js +155 -0
- package/dist/lib/workspace/pending-state.js.map +1 -0
- package/dist/lib/workspace/pending-transactions.d.ts +44 -0
- package/dist/lib/workspace/pending-transactions.d.ts.map +1 -0
- package/dist/lib/workspace/pending-transactions.js +114 -0
- package/dist/lib/workspace/pending-transactions.js.map +1 -0
- package/dist/lib/workspace/tab-kind.d.ts +48 -0
- package/dist/lib/workspace/tab-kind.d.ts.map +1 -0
- package/dist/lib/workspace/tab-kind.js +47 -0
- package/dist/lib/workspace/tab-kind.js.map +1 -0
- package/dist/lib/workspace/tab-state.d.ts +36 -0
- package/dist/lib/workspace/tab-state.d.ts.map +1 -0
- package/dist/lib/workspace/tab-state.js +81 -0
- package/dist/lib/workspace/tab-state.js.map +1 -0
- package/dist/lib/workspace/tabs-state.d.ts +46 -0
- package/dist/lib/workspace/tabs-state.d.ts.map +1 -0
- package/dist/lib/workspace/tabs-state.js +56 -0
- package/dist/lib/workspace/tabs-state.js.map +1 -0
- package/dist/lib/workspace/use-entity-draft.d.ts +25 -0
- package/dist/lib/workspace/use-entity-draft.d.ts.map +1 -0
- package/dist/lib/workspace/use-entity-draft.js +38 -0
- package/dist/lib/workspace/use-entity-draft.js.map +1 -0
- package/dist/lib/workspace/workspace-scope.d.ts +51 -0
- package/dist/lib/workspace/workspace-scope.d.ts.map +1 -0
- package/dist/lib/workspace/workspace-scope.js +42 -0
- package/dist/lib/workspace/workspace-scope.js.map +1 -0
- package/dist/lib/workspace/workspace-shell.d.ts +33 -0
- package/dist/lib/workspace/workspace-shell.d.ts.map +1 -0
- package/dist/lib/workspace/workspace-shell.js +206 -0
- package/dist/lib/workspace/workspace-shell.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +41 -0
- package/dist/server.js.map +1 -0
- package/package.json +95 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 r10c Technologies
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from './lib/back-office/index.js';
|
|
2
|
+
export * from './lib/command-palette/index.js';
|
|
3
|
+
export * from './lib/crud/index.js';
|
|
4
|
+
export * from './lib/i18n/index.js';
|
|
5
|
+
export type * from './lib/search/record-search.types.js';
|
|
6
|
+
export * from './lib/search/search-records.js';
|
|
7
|
+
export * from './lib/session/index.js';
|
|
8
|
+
export type { AccountDestination, AccountLabelKey, AccountLink, } from './lib/session/account-links.js';
|
|
9
|
+
export * from './lib/wizard/index.js';
|
|
10
|
+
export * from './lib/workspace/index.js';
|
|
11
|
+
/**
|
|
12
|
+
* Re-exported, not redeclared. A workspace host holds an entity form's draft to
|
|
13
|
+
* autosave it, so it has to be able to name the type — but the type is core's,
|
|
14
|
+
* and a fourth structural copy of `Record<string, string>` beside
|
|
15
|
+
* `EntityFormValues`/`EntityFormDraft`/`EntityLinkDraft` is exactly what
|
|
16
|
+
* [ADR 0034](../../../../docs/adr/0034-composition-metadata.md) collapsed. One
|
|
17
|
+
* declaration, reachable from the layer its consumers already depend on.
|
|
18
|
+
*/
|
|
19
|
+
export * from './lib/i18n/catalog/index.js';
|
|
20
|
+
export type { EntityDraft } from '@entifix/core';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AAIpC,mBAAmB,qCAAqC,CAAC;AACzD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AAIvC,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,WAAW,GACZ,MAAM,gCAAgC,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AAEzC;;;;;;;GAOG;AACH,cAAc,6BAA6B,CAAC;AAC5C,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Use this file to export React client components (e.g. those with 'use client' directive) or other non-server utilities
|
|
2
|
+
export * from './lib/back-office/index.js';
|
|
3
|
+
export * from './lib/command-palette/index.js';
|
|
4
|
+
export * from './lib/crud/index.js';
|
|
5
|
+
export * from './lib/i18n/index.js';
|
|
6
|
+
export * from './lib/search/search-records.js';
|
|
7
|
+
export * from './lib/session/index.js';
|
|
8
|
+
export * from './lib/wizard/index.js';
|
|
9
|
+
export * from './lib/workspace/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Re-exported, not redeclared. A workspace host holds an entity form's draft to
|
|
12
|
+
* autosave it, so it has to be able to name the type — but the type is core's,
|
|
13
|
+
* and a fourth structural copy of `Record<string, string>` beside
|
|
14
|
+
* `EntityFormValues`/`EntityFormDraft`/`EntityLinkDraft` is exactly what
|
|
15
|
+
* [ADR 0034](../../../../docs/adr/0034-composition-metadata.md) collapsed. One
|
|
16
|
+
* declaration, reachable from the layer its consumers already depend on.
|
|
17
|
+
*/ export * from './lib/i18n/catalog/index.js';
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Use this file to export React client components (e.g. those with 'use client' directive) or other non-server utilities\n\nexport * from './lib/back-office/index.js';\nexport * from './lib/command-palette/index.js';\nexport * from './lib/crud/index.js';\nexport * from './lib/i18n/index.js';\n// The browser half of record search: a typed `fetch` and the shapes it returns.\n// The route handler and the source declarations stay in `/server`, since they\n// read cookies and would be stamped as client references here.\nexport type * from './lib/search/record-search.types.js';\nexport * from './lib/search/search-records.js';\nexport * from './lib/session/index.js';\n// Type-only, so it stays erased: the account-link *values* ship from `/server`\n// (see src/server.ts), but `AccountMenuProps` names these types and a consumer\n// of the client entry has to be able to name them too.\nexport type {\n AccountDestination,\n AccountLabelKey,\n AccountLink,\n} from './lib/session/account-links.js';\nexport * from './lib/wizard/index.js';\nexport * from './lib/workspace/index.js';\n\n/**\n * Re-exported, not redeclared. A workspace host holds an entity form's draft to\n * autosave it, so it has to be able to name the type — but the type is core's,\n * and a fourth structural copy of `Record<string, string>` beside\n * `EntityFormValues`/`EntityFormDraft`/`EntityLinkDraft` is exactly what\n * [ADR 0034](../../../../docs/adr/0034-composition-metadata.md) collapsed. One\n * declaration, reachable from the layer its consumers already depend on.\n */\nexport * from './lib/i18n/catalog/index.js';\nexport type { EntityDraft } from '@entifix/core';\n"],"names":[],"mappings":"AAAA,yHAAyH;AAEzH,cAAc,6BAA6B;AAC3C,cAAc,iCAAiC;AAC/C,cAAc,sBAAsB;AACpC,cAAc,sBAAsB;AAKpC,cAAc,iCAAiC;AAC/C,cAAc,yBAAyB;AASvC,cAAc,wBAAwB;AACtC,cAAc,2BAA2B;AAEzC;;;;;;;CAOC,GACD,cAAc,8BAA8B"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AccountLink } from '../session/account-links.js';
|
|
2
|
+
export interface AccountMenuProps {
|
|
3
|
+
/** Trigger text — typically the signed-in subject. */
|
|
4
|
+
readonly label: string;
|
|
5
|
+
/**
|
|
6
|
+
* Built by the host from `accountPaths()`, which is where the request's
|
|
7
|
+
* locale is known. Only the `href` is the host's to supply; the copy is this
|
|
8
|
+
* component's own.
|
|
9
|
+
*/
|
|
10
|
+
readonly items: readonly AccountLink[];
|
|
11
|
+
/** Where this app mounts its logout handler. */
|
|
12
|
+
readonly signOutEndpoint?: string;
|
|
13
|
+
/** Fallback destination if logout answers without one. */
|
|
14
|
+
readonly signOutRedirect?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The top-bar account menu.
|
|
18
|
+
*
|
|
19
|
+
* Entries are plain links rather than router pushes: they are ordinary
|
|
20
|
+
* navigations, and were absolute cross-origin URLs back when the account
|
|
21
|
+
* surface lived in its own app. Unlike `nav`, whose labels are authored by the
|
|
22
|
+
* host app, this menu's copy is authored here — so it is resolved here, out of
|
|
23
|
+
* `shell:account.*`, and the host supplies only URLs.
|
|
24
|
+
*
|
|
25
|
+
* Showing or hiding an entry here protects nothing; auth-service refuses the
|
|
26
|
+
* request. This is navigation, not authorization.
|
|
27
|
+
*/
|
|
28
|
+
export declare function AccountMenu({ label, items, signOutEndpoint, signOutRedirect, }: AccountMenuProps): import("react").JSX.Element;
|
|
29
|
+
//# sourceMappingURL=account-menu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-menu.d.ts","sourceRoot":"","sources":["../../../src/lib/back-office/account-menu.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,gDAAgD;IAChD,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,0DAA0D;IAC1D,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAK,EACL,eAAoC,EACpC,eAAqB,GACtB,EAAE,gBAAgB,+BA8ClB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Menu, useT } from '@entifix/react-controls';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
/**
|
|
6
|
+
* The top-bar account menu.
|
|
7
|
+
*
|
|
8
|
+
* Entries are plain links rather than router pushes: they are ordinary
|
|
9
|
+
* navigations, and were absolute cross-origin URLs back when the account
|
|
10
|
+
* surface lived in its own app. Unlike `nav`, whose labels are authored by the
|
|
11
|
+
* host app, this menu's copy is authored here — so it is resolved here, out of
|
|
12
|
+
* `shell:account.*`, and the host supplies only URLs.
|
|
13
|
+
*
|
|
14
|
+
* Showing or hiding an entry here protects nothing; auth-service refuses the
|
|
15
|
+
* request. This is navigation, not authorization.
|
|
16
|
+
*/ export function AccountMenu({ label, items, signOutEndpoint = '/api/auth/logout', signOutRedirect = '/' }) {
|
|
17
|
+
const t = useT('shell');
|
|
18
|
+
const [pending, setPending] = useState(false);
|
|
19
|
+
const signOut = async ()=>{
|
|
20
|
+
setPending(true);
|
|
21
|
+
try {
|
|
22
|
+
var _ref, _body_endSessionUrl;
|
|
23
|
+
const response = await fetch(signOutEndpoint, {
|
|
24
|
+
method: 'POST',
|
|
25
|
+
cache: 'no-store'
|
|
26
|
+
});
|
|
27
|
+
const body = await response.json();
|
|
28
|
+
// The provider's end-session URL wins when the handler returns one.
|
|
29
|
+
// Clearing our cookies alone leaves someone "signed out" who is one click
|
|
30
|
+
// from being signed straight back in with no prompt, because the provider
|
|
31
|
+
// still holds a session — which on a shared machine is the failure this
|
|
32
|
+
// whole control exists to prevent.
|
|
33
|
+
window.location.href = (_ref = (_body_endSessionUrl = body.endSessionUrl) != null ? _body_endSessionUrl : body.redirect) != null ? _ref : signOutRedirect;
|
|
34
|
+
} catch (unused) {
|
|
35
|
+
// The cookies may already be gone; get out of the protected area anyway.
|
|
36
|
+
window.location.href = signOutRedirect;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
return /*#__PURE__*/ _jsxs(Menu, {
|
|
40
|
+
children: [
|
|
41
|
+
/*#__PURE__*/ _jsxs(Menu.Trigger, {
|
|
42
|
+
"aria-label": label,
|
|
43
|
+
children: [
|
|
44
|
+
/*#__PURE__*/ _jsx("span", {
|
|
45
|
+
"aria-hidden": "true",
|
|
46
|
+
children: "◕"
|
|
47
|
+
}),
|
|
48
|
+
/*#__PURE__*/ _jsx("span", {
|
|
49
|
+
children: label
|
|
50
|
+
})
|
|
51
|
+
]
|
|
52
|
+
}),
|
|
53
|
+
/*#__PURE__*/ _jsxs(Menu.Items, {
|
|
54
|
+
children: [
|
|
55
|
+
items.map((item)=>/*#__PURE__*/ _jsx(Menu.Link, {
|
|
56
|
+
href: item.href,
|
|
57
|
+
children: t(item.labelKey)
|
|
58
|
+
}, item.href)),
|
|
59
|
+
/*#__PURE__*/ _jsx(Menu.Item, {
|
|
60
|
+
onClick: signOut,
|
|
61
|
+
disabled: pending,
|
|
62
|
+
children: t('account.signOut')
|
|
63
|
+
})
|
|
64
|
+
]
|
|
65
|
+
})
|
|
66
|
+
]
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=account-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/back-office/account-menu.tsx"],"sourcesContent":["'use client';\n\nimport { Menu, useT } from '@entifix/react-controls';\nimport { useState } from 'react';\n\nimport type { AccountLink } from '../session/account-links.js';\n\nexport interface AccountMenuProps {\n /** Trigger text — typically the signed-in subject. */\n readonly label: string;\n /**\n * Built by the host from `accountPaths()`, which is where the request's\n * locale is known. Only the `href` is the host's to supply; the copy is this\n * component's own.\n */\n readonly items: readonly AccountLink[];\n /** Where this app mounts its logout handler. */\n readonly signOutEndpoint?: string;\n /** Fallback destination if logout answers without one. */\n readonly signOutRedirect?: string;\n}\n\n/**\n * The top-bar account menu.\n *\n * Entries are plain links rather than router pushes: they are ordinary\n * navigations, and were absolute cross-origin URLs back when the account\n * surface lived in its own app. Unlike `nav`, whose labels are authored by the\n * host app, this menu's copy is authored here — so it is resolved here, out of\n * `shell:account.*`, and the host supplies only URLs.\n *\n * Showing or hiding an entry here protects nothing; auth-service refuses the\n * request. This is navigation, not authorization.\n */\nexport function AccountMenu({\n label,\n items,\n signOutEndpoint = '/api/auth/logout',\n signOutRedirect = '/',\n}: AccountMenuProps) {\n const t = useT('shell');\n const [pending, setPending] = useState(false);\n\n const signOut = async () => {\n setPending(true);\n try {\n const response = await fetch(signOutEndpoint, {\n method: 'POST',\n cache: 'no-store',\n });\n const body = (await response.json()) as {\n redirect?: string;\n endSessionUrl?: string;\n };\n // The provider's end-session URL wins when the handler returns one.\n // Clearing our cookies alone leaves someone \"signed out\" who is one click\n // from being signed straight back in with no prompt, because the provider\n // still holds a session — which on a shared machine is the failure this\n // whole control exists to prevent.\n window.location.href =\n body.endSessionUrl ?? body.redirect ?? signOutRedirect;\n } catch {\n // The cookies may already be gone; get out of the protected area anyway.\n window.location.href = signOutRedirect;\n }\n };\n\n return (\n <Menu>\n <Menu.Trigger aria-label={label}>\n <span aria-hidden=\"true\">◕</span>\n <span>{label}</span>\n </Menu.Trigger>\n <Menu.Items>\n {items.map(item => (\n <Menu.Link key={item.href} href={item.href}>\n {t(item.labelKey)}\n </Menu.Link>\n ))}\n <Menu.Item onClick={signOut} disabled={pending}>\n {t('account.signOut')}\n </Menu.Item>\n </Menu.Items>\n </Menu>\n );\n}\n"],"names":["Menu","useT","useState","AccountMenu","label","items","signOutEndpoint","signOutRedirect","t","pending","setPending","signOut","body","response","fetch","method","cache","json","window","location","href","endSessionUrl","redirect","Trigger","aria-label","span","aria-hidden","Items","map","item","Link","labelKey","Item","onClick","disabled"],"mappings":"AAAA;;AAEA,SAASA,IAAI,EAAEC,IAAI,QAAQ,0BAA0B;AACrD,SAASC,QAAQ,QAAQ,QAAQ;AAmBjC;;;;;;;;;;;CAWC,GACD,OAAO,SAASC,YAAY,EAC1BC,KAAK,EACLC,KAAK,EACLC,kBAAkB,kBAAkB,EACpCC,kBAAkB,GAAG,EACJ;IACjB,MAAMC,IAAIP,KAAK;IACf,MAAM,CAACQ,SAASC,WAAW,GAAGR,SAAS;IAEvC,MAAMS,UAAU;QACdD,WAAW;QACX,IAAI;gBAeAE,MAAAA;YAdF,MAAMC,WAAW,MAAMC,MAAMR,iBAAiB;gBAC5CS,QAAQ;gBACRC,OAAO;YACT;YACA,MAAMJ,OAAQ,MAAMC,SAASI,IAAI;YAIjC,oEAAoE;YACpE,0EAA0E;YAC1E,0EAA0E;YAC1E,wEAAwE;YACxE,mCAAmC;YACnCC,OAAOC,QAAQ,CAACC,IAAI,IAClBR,QAAAA,sBAAAA,KAAKS,aAAa,YAAlBT,sBAAsBA,KAAKU,QAAQ,YAAnCV,OAAuCL;QAC3C,EAAE,eAAM;YACN,yEAAyE;YACzEW,OAAOC,QAAQ,CAACC,IAAI,GAAGb;QACzB;IACF;IAEA,qBACE,MAACP;;0BACC,MAACA,KAAKuB,OAAO;gBAACC,cAAYpB;;kCACxB,KAACqB;wBAAKC,eAAY;kCAAO;;kCACzB,KAACD;kCAAMrB;;;;0BAET,MAACJ,KAAK2B,KAAK;;oBACRtB,MAAMuB,GAAG,CAACC,CAAAA,qBACT,KAAC7B,KAAK8B,IAAI;4BAAiBV,MAAMS,KAAKT,IAAI;sCACvCZ,EAAEqB,KAAKE,QAAQ;2BADFF,KAAKT,IAAI;kCAI3B,KAACpB,KAAKgC,IAAI;wBAACC,SAAStB;wBAASuB,UAAUzB;kCACpCD,EAAE;;;;;;AAKb"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { NavSection } from './nav.js';
|
|
3
|
+
export interface BackOfficeShellProps {
|
|
4
|
+
/** Grouped primary navigation. */
|
|
5
|
+
nav: NavSection[];
|
|
6
|
+
/** Brand mark shown at the top of the sidebar. */
|
|
7
|
+
brand: ReactNode;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
/** Segment → label overrides for the breadcrumb trail. */
|
|
10
|
+
breadcrumbLabels?: Record<string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* Right-aligned slot in the top bar — the account menu. A slot rather than a
|
|
13
|
+
* built-in, because what belongs in it differs per host: the label is the
|
|
14
|
+
* signed-in subject where a layout has resolved a principal, and a bare
|
|
15
|
+
* caption where it has not.
|
|
16
|
+
*/
|
|
17
|
+
accountMenu?: ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* The command palette, trigger and all.
|
|
20
|
+
*
|
|
21
|
+
* A slot for a reason the account menu does not share: the palette's use-case
|
|
22
|
+
* sources carry entity constructors and handler functions, neither of which
|
|
23
|
+
* survives the server→client boundary, so it cannot be built from serializable
|
|
24
|
+
* props here. The host composes it in a client module of its own and hands it
|
|
25
|
+
* over — which also keeps this `shell:base` package from naming any domain's
|
|
26
|
+
* entities.
|
|
27
|
+
*/
|
|
28
|
+
commandPalette?: ReactNode;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Back-office page shell: a collapsible sidebar + a top bar carrying
|
|
32
|
+
* breadcrumbs, wrapping the routed content. Composed from the agnostic
|
|
33
|
+
* `Sidebar` primitive — the Next coupling (routing, breadcrumbs) lives here,
|
|
34
|
+
* not in the primitive.
|
|
35
|
+
*
|
|
36
|
+
* **Collapse has two inputs, and only one of them is a preference.** The stored
|
|
37
|
+
* choice is the person's; a `rail`-width viewport forces the compact form
|
|
38
|
+
* whatever they chose. They are kept apart deliberately: writing the forced
|
|
39
|
+
* value back would mean a single visit at a narrow width silently rewrites the
|
|
40
|
+
* choice, and the sidebar comes back collapsed on the desktop the person set it
|
|
41
|
+
* expanded on.
|
|
42
|
+
*
|
|
43
|
+
* Below `rail` the sidebar is not a sidebar at all — it is a drawer, built on
|
|
44
|
+
* Headless UI's `Dialog` for the focus trap, `Escape` handling, backdrop click
|
|
45
|
+
* and focus restoration that a hand-rolled one has to get right and usually does
|
|
46
|
+
* not. There is exactly one `SidebarNav` in the tree either way; rendering a
|
|
47
|
+
* second copy for the drawer is how the two drift.
|
|
48
|
+
*/
|
|
49
|
+
export declare function BackOfficeShell({ nav, brand, children, breadcrumbLabels, accountMenu, commandPalette, }: BackOfficeShellProps): import("react").JSX.Element;
|
|
50
|
+
//# sourceMappingURL=back-office-shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"back-office-shell.d.ts","sourceRoot":"","sources":["../../../src/lib/back-office/back-office-shell.tsx"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;AAGjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAa3C,MAAM,WAAW,oBAAoB;IACnC,kCAAkC;IAClC,GAAG,EAAE,UAAU,EAAE,CAAC;IAClB,kDAAkD;IAClD,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,WAAW,EACX,cAAc,GACf,EAAE,oBAAoB,+BAkGtB"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { Button, Drawer, Sidebar, useT, useUiPreference, useViewportMode } from '@entifix/react-controls';
|
|
5
|
+
import { usePathname } from 'next/navigation';
|
|
6
|
+
import { useState } from 'react';
|
|
7
|
+
import { BackOfficeBreadcrumbs } from './breadcrumbs.js';
|
|
8
|
+
import { SidebarNav } from './sidebar-nav.js';
|
|
9
|
+
/** `namespace:` is prepended by the store → `entifix-ui:back-office:sidebar-collapsed`. */ const SIDEBAR_PREF_KEY = 'back-office:sidebar-collapsed';
|
|
10
|
+
/**
|
|
11
|
+
* Which domain groups are collapsed, as one keyed record rather than a key per
|
|
12
|
+
* group. `useUiPreference` resolves asynchronously after mount, so N keys would
|
|
13
|
+
* be N first-paint transitions; one read settles the whole sidebar at once.
|
|
14
|
+
*/ const NAV_GROUPS_PREF_KEY = 'back-office:nav-collapsed-groups';
|
|
15
|
+
/**
|
|
16
|
+
* Back-office page shell: a collapsible sidebar + a top bar carrying
|
|
17
|
+
* breadcrumbs, wrapping the routed content. Composed from the agnostic
|
|
18
|
+
* `Sidebar` primitive — the Next coupling (routing, breadcrumbs) lives here,
|
|
19
|
+
* not in the primitive.
|
|
20
|
+
*
|
|
21
|
+
* **Collapse has two inputs, and only one of them is a preference.** The stored
|
|
22
|
+
* choice is the person's; a `rail`-width viewport forces the compact form
|
|
23
|
+
* whatever they chose. They are kept apart deliberately: writing the forced
|
|
24
|
+
* value back would mean a single visit at a narrow width silently rewrites the
|
|
25
|
+
* choice, and the sidebar comes back collapsed on the desktop the person set it
|
|
26
|
+
* expanded on.
|
|
27
|
+
*
|
|
28
|
+
* Below `rail` the sidebar is not a sidebar at all — it is a drawer, built on
|
|
29
|
+
* Headless UI's `Dialog` for the focus trap, `Escape` handling, backdrop click
|
|
30
|
+
* and focus restoration that a hand-rolled one has to get right and usually does
|
|
31
|
+
* not. There is exactly one `SidebarNav` in the tree either way; rendering a
|
|
32
|
+
* second copy for the drawer is how the two drift.
|
|
33
|
+
*/ export function BackOfficeShell({ nav, brand, children, breadcrumbLabels, accountMenu, commandPalette }) {
|
|
34
|
+
const t = useT('shell');
|
|
35
|
+
const mode = useViewportMode();
|
|
36
|
+
const pathname = usePathname();
|
|
37
|
+
const { value: preferCollapsed, setValue: setCollapsed } = useUiPreference(SIDEBAR_PREF_KEY, false);
|
|
38
|
+
const { value: collapsedGroups, setValue: setCollapsedGroups } = useUiPreference(NAV_GROUPS_PREF_KEY, {});
|
|
39
|
+
// The drawer remembers *where* it was opened, and is open only while the
|
|
40
|
+
// visitor is still there. A drawer that survives navigation covers the page
|
|
41
|
+
// they just asked for, and closing it from an effect keyed on the route would
|
|
42
|
+
// set state during a passive effect — a cascading render for something that is
|
|
43
|
+
// derivable, since "still on the page I opened this from" is a fact about the
|
|
44
|
+
// current render rather than an event to react to.
|
|
45
|
+
const [openedAt, setOpenedAt] = useState(null);
|
|
46
|
+
const isDrawerOpen = openedAt !== null && openedAt === pathname;
|
|
47
|
+
const setDrawerOpen = (open)=>setOpenedAt(open ? pathname : null);
|
|
48
|
+
// Three modes, one answer. A drawer has the whole viewport's width, so it
|
|
49
|
+
// shows labels whatever the stored preference says — that preference is about
|
|
50
|
+
// how much room the sidebar should take beside the content, and in a drawer
|
|
51
|
+
// there is no beside.
|
|
52
|
+
const collapsed = mode === 'rail' ? true : mode === 'compact' ? false : preferCollapsed;
|
|
53
|
+
const toggleGroup = (title)=>setCollapsedGroups(_extends({}, collapsedGroups, {
|
|
54
|
+
[title]: collapsedGroups[title] !== true
|
|
55
|
+
}));
|
|
56
|
+
const navTree = /*#__PURE__*/ _jsx(SidebarNav, {
|
|
57
|
+
sections: nav,
|
|
58
|
+
collapsed: collapsed,
|
|
59
|
+
collapsedGroups: collapsedGroups,
|
|
60
|
+
onToggleGroup: toggleGroup
|
|
61
|
+
});
|
|
62
|
+
const isCompact = mode === 'compact';
|
|
63
|
+
return /*#__PURE__*/ _jsxs(Sidebar, {
|
|
64
|
+
gap: "none",
|
|
65
|
+
className: "min-h-screen",
|
|
66
|
+
children: [
|
|
67
|
+
isCompact ? null : /*#__PURE__*/ _jsxs(Sidebar.Side, {
|
|
68
|
+
as: "aside",
|
|
69
|
+
width: collapsed ? '4.5rem' : '16rem',
|
|
70
|
+
className: "md:sticky md:top-0 md:h-screen md:overflow-y-auto flex flex-col gap-m border-r border-border bg-surface-elevated p-s",
|
|
71
|
+
children: [
|
|
72
|
+
/*#__PURE__*/ _jsx("div", {
|
|
73
|
+
className: "flex items-center justify-center px-2xs py-3xs text-step-1 font-semibold text-content",
|
|
74
|
+
children: collapsed ? null : brand
|
|
75
|
+
}),
|
|
76
|
+
navTree
|
|
77
|
+
]
|
|
78
|
+
}),
|
|
79
|
+
/*#__PURE__*/ _jsxs(Sidebar.Main, {
|
|
80
|
+
as: "main",
|
|
81
|
+
className: "flex flex-col",
|
|
82
|
+
children: [
|
|
83
|
+
/*#__PURE__*/ _jsxs("header", {
|
|
84
|
+
className: "flex items-center gap-s border-b border-border bg-surface-elevated px-m py-s",
|
|
85
|
+
children: [
|
|
86
|
+
/*#__PURE__*/ _jsx(Button, _extends({
|
|
87
|
+
variant: "ghost",
|
|
88
|
+
size: "sm",
|
|
89
|
+
"aria-label": isCompact ? t('sidebar.openMenu') : collapsed ? t('sidebar.expand') : t('sidebar.collapse')
|
|
90
|
+
}, isCompact ? {} : {
|
|
91
|
+
'aria-pressed': collapsed
|
|
92
|
+
}, {
|
|
93
|
+
onClick: ()=>isCompact ? setDrawerOpen(true) : setCollapsed(!preferCollapsed),
|
|
94
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
95
|
+
"aria-hidden": "true",
|
|
96
|
+
children: "☰"
|
|
97
|
+
})
|
|
98
|
+
})),
|
|
99
|
+
/*#__PURE__*/ _jsx(BackOfficeBreadcrumbs, {
|
|
100
|
+
labels: breadcrumbLabels
|
|
101
|
+
}),
|
|
102
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
103
|
+
className: "ml-auto flex items-center gap-2xs",
|
|
104
|
+
children: [
|
|
105
|
+
commandPalette,
|
|
106
|
+
accountMenu
|
|
107
|
+
]
|
|
108
|
+
})
|
|
109
|
+
]
|
|
110
|
+
}),
|
|
111
|
+
/*#__PURE__*/ _jsx("div", {
|
|
112
|
+
className: "flex-1 p-m",
|
|
113
|
+
children: children
|
|
114
|
+
})
|
|
115
|
+
]
|
|
116
|
+
}),
|
|
117
|
+
isCompact && /*#__PURE__*/ _jsx(Drawer, {
|
|
118
|
+
open: isDrawerOpen,
|
|
119
|
+
onClose: ()=>setDrawerOpen(false),
|
|
120
|
+
title: brand,
|
|
121
|
+
closeLabel: t('sidebar.closeMenu'),
|
|
122
|
+
children: navTree
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=back-office-shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/back-office/back-office-shell.tsx"],"sourcesContent":["'use client';\n\nimport {\n Button,\n Drawer,\n Sidebar,\n useT,\n useUiPreference,\n useViewportMode,\n} from '@entifix/react-controls';\nimport { usePathname } from 'next/navigation';\nimport { type ReactNode, useState } from 'react';\n\nimport { BackOfficeBreadcrumbs } from './breadcrumbs.js';\nimport type { NavSection } from './nav.js';\nimport { SidebarNav } from './sidebar-nav.js';\n\n/** `namespace:` is prepended by the store → `entifix-ui:back-office:sidebar-collapsed`. */\nconst SIDEBAR_PREF_KEY = 'back-office:sidebar-collapsed';\n\n/**\n * Which domain groups are collapsed, as one keyed record rather than a key per\n * group. `useUiPreference` resolves asynchronously after mount, so N keys would\n * be N first-paint transitions; one read settles the whole sidebar at once.\n */\nconst NAV_GROUPS_PREF_KEY = 'back-office:nav-collapsed-groups';\n\nexport interface BackOfficeShellProps {\n /** Grouped primary navigation. */\n nav: NavSection[];\n /** Brand mark shown at the top of the sidebar. */\n brand: ReactNode;\n children: ReactNode;\n /** Segment → label overrides for the breadcrumb trail. */\n breadcrumbLabels?: Record<string, string>;\n /**\n * Right-aligned slot in the top bar — the account menu. A slot rather than a\n * built-in, because what belongs in it differs per host: the label is the\n * signed-in subject where a layout has resolved a principal, and a bare\n * caption where it has not.\n */\n accountMenu?: ReactNode;\n /**\n * The command palette, trigger and all.\n *\n * A slot for a reason the account menu does not share: the palette's use-case\n * sources carry entity constructors and handler functions, neither of which\n * survives the server→client boundary, so it cannot be built from serializable\n * props here. The host composes it in a client module of its own and hands it\n * over — which also keeps this `shell:base` package from naming any domain's\n * entities.\n */\n commandPalette?: ReactNode;\n}\n\n/**\n * Back-office page shell: a collapsible sidebar + a top bar carrying\n * breadcrumbs, wrapping the routed content. Composed from the agnostic\n * `Sidebar` primitive — the Next coupling (routing, breadcrumbs) lives here,\n * not in the primitive.\n *\n * **Collapse has two inputs, and only one of them is a preference.** The stored\n * choice is the person's; a `rail`-width viewport forces the compact form\n * whatever they chose. They are kept apart deliberately: writing the forced\n * value back would mean a single visit at a narrow width silently rewrites the\n * choice, and the sidebar comes back collapsed on the desktop the person set it\n * expanded on.\n *\n * Below `rail` the sidebar is not a sidebar at all — it is a drawer, built on\n * Headless UI's `Dialog` for the focus trap, `Escape` handling, backdrop click\n * and focus restoration that a hand-rolled one has to get right and usually does\n * not. There is exactly one `SidebarNav` in the tree either way; rendering a\n * second copy for the drawer is how the two drift.\n */\nexport function BackOfficeShell({\n nav,\n brand,\n children,\n breadcrumbLabels,\n accountMenu,\n commandPalette,\n}: BackOfficeShellProps) {\n const t = useT('shell');\n const mode = useViewportMode();\n const pathname = usePathname();\n const { value: preferCollapsed, setValue: setCollapsed } =\n useUiPreference<boolean>(SIDEBAR_PREF_KEY, false);\n const { value: collapsedGroups, setValue: setCollapsedGroups } =\n useUiPreference<Record<string, boolean>>(NAV_GROUPS_PREF_KEY, {});\n // The drawer remembers *where* it was opened, and is open only while the\n // visitor is still there. A drawer that survives navigation covers the page\n // they just asked for, and closing it from an effect keyed on the route would\n // set state during a passive effect — a cascading render for something that is\n // derivable, since \"still on the page I opened this from\" is a fact about the\n // current render rather than an event to react to.\n const [openedAt, setOpenedAt] = useState<string | null>(null);\n const isDrawerOpen = openedAt !== null && openedAt === pathname;\n const setDrawerOpen = (open: boolean) => setOpenedAt(open ? pathname : null);\n\n // Three modes, one answer. A drawer has the whole viewport's width, so it\n // shows labels whatever the stored preference says — that preference is about\n // how much room the sidebar should take beside the content, and in a drawer\n // there is no beside.\n const collapsed =\n mode === 'rail' ? true : mode === 'compact' ? false : preferCollapsed;\n const toggleGroup = (title: string) =>\n setCollapsedGroups({\n ...collapsedGroups,\n [title]: collapsedGroups[title] !== true,\n });\n\n const navTree = (\n <SidebarNav\n sections={nav}\n collapsed={collapsed}\n collapsedGroups={collapsedGroups}\n onToggleGroup={toggleGroup}\n />\n );\n\n const isCompact = mode === 'compact';\n\n return (\n <Sidebar gap=\"none\" className=\"min-h-screen\">\n {isCompact ? null : (\n <Sidebar.Side\n as=\"aside\"\n width={collapsed ? '4.5rem' : '16rem'}\n className=\"md:sticky md:top-0 md:h-screen md:overflow-y-auto flex flex-col gap-m border-r border-border bg-surface-elevated p-s\"\n >\n <div className=\"flex items-center justify-center px-2xs py-3xs text-step-1 font-semibold text-content\">\n {collapsed ? null : brand}\n </div>\n {navTree}\n </Sidebar.Side>\n )}\n\n <Sidebar.Main as=\"main\" className=\"flex flex-col\">\n <header className=\"flex items-center gap-s border-b border-border bg-surface-elevated px-m py-s\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={\n isCompact\n ? t('sidebar.openMenu')\n : collapsed\n ? t('sidebar.expand')\n : t('sidebar.collapse')\n }\n // A drawer trigger is not a two-state toggle — it opens a thing that\n // closes itself — so it reports pressed state only where it is one.\n {...(isCompact ? {} : { 'aria-pressed': collapsed })}\n onClick={() =>\n isCompact ? setDrawerOpen(true) : setCollapsed(!preferCollapsed)\n }\n >\n <span aria-hidden=\"true\">☰</span>\n </Button>\n <BackOfficeBreadcrumbs labels={breadcrumbLabels} />\n <div className=\"ml-auto flex items-center gap-2xs\">\n {commandPalette}\n {accountMenu}\n </div>\n </header>\n <div className=\"flex-1 p-m\">{children}</div>\n </Sidebar.Main>\n\n {isCompact && (\n <Drawer\n open={isDrawerOpen}\n onClose={() => setDrawerOpen(false)}\n title={brand}\n closeLabel={t('sidebar.closeMenu')}\n >\n {navTree}\n </Drawer>\n )}\n </Sidebar>\n );\n}\n"],"names":["Button","Drawer","Sidebar","useT","useUiPreference","useViewportMode","usePathname","useState","BackOfficeBreadcrumbs","SidebarNav","SIDEBAR_PREF_KEY","NAV_GROUPS_PREF_KEY","BackOfficeShell","nav","brand","children","breadcrumbLabels","accountMenu","commandPalette","t","mode","pathname","value","preferCollapsed","setValue","setCollapsed","collapsedGroups","setCollapsedGroups","openedAt","setOpenedAt","isDrawerOpen","setDrawerOpen","open","collapsed","toggleGroup","title","navTree","sections","onToggleGroup","isCompact","gap","className","Side","as","width","div","Main","header","variant","size","aria-label","onClick","span","aria-hidden","labels","onClose","closeLabel"],"mappings":"AAAA;;;AAEA,SACEA,MAAM,EACNC,MAAM,EACNC,OAAO,EACPC,IAAI,EACJC,eAAe,EACfC,eAAe,QACV,0BAA0B;AACjC,SAASC,WAAW,QAAQ,kBAAkB;AAC9C,SAAyBC,QAAQ,QAAQ,QAAQ;AAEjD,SAASC,qBAAqB,QAAQ,mBAAmB;AAEzD,SAASC,UAAU,QAAQ,mBAAmB;AAE9C,yFAAyF,GACzF,MAAMC,mBAAmB;AAEzB;;;;CAIC,GACD,MAAMC,sBAAsB;AA8B5B;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,SAASC,gBAAgB,EAC9BC,GAAG,EACHC,KAAK,EACLC,QAAQ,EACRC,gBAAgB,EAChBC,WAAW,EACXC,cAAc,EACO;IACrB,MAAMC,IAAIhB,KAAK;IACf,MAAMiB,OAAOf;IACb,MAAMgB,WAAWf;IACjB,MAAM,EAAEgB,OAAOC,eAAe,EAAEC,UAAUC,YAAY,EAAE,GACtDrB,gBAAyBM,kBAAkB;IAC7C,MAAM,EAAEY,OAAOI,eAAe,EAAEF,UAAUG,kBAAkB,EAAE,GAC5DvB,gBAAyCO,qBAAqB,CAAC;IACjE,yEAAyE;IACzE,4EAA4E;IAC5E,8EAA8E;IAC9E,+EAA+E;IAC/E,8EAA8E;IAC9E,mDAAmD;IACnD,MAAM,CAACiB,UAAUC,YAAY,GAAGtB,SAAwB;IACxD,MAAMuB,eAAeF,aAAa,QAAQA,aAAaP;IACvD,MAAMU,gBAAgB,CAACC,OAAkBH,YAAYG,OAAOX,WAAW;IAEvE,0EAA0E;IAC1E,8EAA8E;IAC9E,4EAA4E;IAC5E,sBAAsB;IACtB,MAAMY,YACJb,SAAS,SAAS,OAAOA,SAAS,YAAY,QAAQG;IACxD,MAAMW,cAAc,CAACC,QACnBR,mBAAmB,aACdD;YACH,CAACS,MAAM,EAAET,eAAe,CAACS,MAAM,KAAK;;IAGxC,MAAMC,wBACJ,KAAC3B;QACC4B,UAAUxB;QACVoB,WAAWA;QACXP,iBAAiBA;QACjBY,eAAeJ;;IAInB,MAAMK,YAAYnB,SAAS;IAE3B,qBACE,MAAClB;QAAQsC,KAAI;QAAOC,WAAU;;YAC3BF,YAAY,qBACX,MAACrC,QAAQwC,IAAI;gBACXC,IAAG;gBACHC,OAAOX,YAAY,WAAW;gBAC9BQ,WAAU;;kCAEV,KAACI;wBAAIJ,WAAU;kCACZR,YAAY,OAAOnB;;oBAErBsB;;;0BAIL,MAAClC,QAAQ4C,IAAI;gBAACH,IAAG;gBAAOF,WAAU;;kCAChC,MAACM;wBAAON,WAAU;;0CAChB,KAACzC;gCACCgD,SAAQ;gCACRC,MAAK;gCACLC,cACEX,YACIpB,EAAE,sBACFc,YACEd,EAAE,oBACFA,EAAE;+BAILoB,YAAY,CAAC,IAAI;gCAAE,gBAAgBN;4BAAU;gCAClDkB,SAAS,IACPZ,YAAYR,cAAc,QAAQN,aAAa,CAACF;0CAGlD,cAAA,KAAC6B;oCAAKC,eAAY;8CAAO;;;0CAE3B,KAAC7C;gCAAsB8C,QAAQtC;;0CAC/B,MAAC6B;gCAAIJ,WAAU;;oCACZvB;oCACAD;;;;;kCAGL,KAAC4B;wBAAIJ,WAAU;kCAAc1B;;;;YAG9BwB,2BACC,KAACtC;gBACC+B,MAAMF;gBACNyB,SAAS,IAAMxB,cAAc;gBAC7BI,OAAOrB;gBACP0C,YAAYrC,EAAE;0BAEbiB;;;;AAKX"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type BreadcrumbItem } from '@entifix/react-controls';
|
|
2
|
+
export interface BackOfficeBreadcrumbsProps {
|
|
3
|
+
/** Map a path segment to an already-translated label; unmapped segments are
|
|
4
|
+
* title-cased. Hosts resolve these through `useT` — the shell has no way to
|
|
5
|
+
* know which namespace an app keeps its route names in. */
|
|
6
|
+
labels?: Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
/** Derives the crumb trail from a pathname. Exported for unit testing. */
|
|
9
|
+
export declare function buildCrumbs(pathname: string, labels: Record<string, string>, homeLabel: string): BreadcrumbItem[];
|
|
10
|
+
/**
|
|
11
|
+
* The root crumb is the shell's own copy: it names the shell's `/`, not
|
|
12
|
+
* anything the host app authored. Apps used to pass their brand here
|
|
13
|
+
* ("Admin", "Identidad"), which duplicated what the sidebar already shows.
|
|
14
|
+
*/
|
|
15
|
+
export declare function BackOfficeBreadcrumbs({ labels, }: BackOfficeBreadcrumbsProps): import("react").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=breadcrumbs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../../src/lib/back-office/breadcrumbs.tsx"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,cAAc,EAGpB,MAAM,yBAAyB,CAAC;AAKjC,MAAM,WAAW,0BAA0B;IACzC;;gEAE4D;IAC5D,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAMD,0EAA0E;AAC1E,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,SAAS,EAAE,MAAM,GAChB,cAAc,EAAE,CAclB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,MAAW,GACZ,EAAE,0BAA0B,+BAe5B"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { splitLocalePath } from '@entifix/core';
|
|
4
|
+
import { Breadcrumbs, useT } from '@entifix/react-controls';
|
|
5
|
+
import { usePathname } from 'next/navigation';
|
|
6
|
+
import { LocaleLink } from '../i18n/index.js';
|
|
7
|
+
function humanize(segment) {
|
|
8
|
+
return segment.replace(/-/g, ' ').replace(/\b\w/g, (c)=>c.toUpperCase());
|
|
9
|
+
}
|
|
10
|
+
/** Derives the crumb trail from a pathname. Exported for unit testing. */ export function buildCrumbs(pathname, labels, homeLabel) {
|
|
11
|
+
const crumbs = [
|
|
12
|
+
{
|
|
13
|
+
label: homeLabel,
|
|
14
|
+
href: '/'
|
|
15
|
+
}
|
|
16
|
+
];
|
|
17
|
+
let href = '';
|
|
18
|
+
// The locale prefix is routing, not a place — a crumb reading "Es" would be
|
|
19
|
+
// both meaningless and un-navigable.
|
|
20
|
+
const { rest } = splitLocalePath(pathname);
|
|
21
|
+
for (const segment of rest.split('/').filter(Boolean)){
|
|
22
|
+
var _labels_segment;
|
|
23
|
+
href += `/${segment}`;
|
|
24
|
+
crumbs.push({
|
|
25
|
+
label: (_labels_segment = labels[segment]) != null ? _labels_segment : humanize(segment),
|
|
26
|
+
href
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
// The last crumb is the current page: drop its href so it renders as such.
|
|
30
|
+
const last = crumbs[crumbs.length - 1];
|
|
31
|
+
last.href = undefined;
|
|
32
|
+
return crumbs;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The root crumb is the shell's own copy: it names the shell's `/`, not
|
|
36
|
+
* anything the host app authored. Apps used to pass their brand here
|
|
37
|
+
* ("Admin", "Identidad"), which duplicated what the sidebar already shows.
|
|
38
|
+
*/ export function BackOfficeBreadcrumbs({ labels = {} }) {
|
|
39
|
+
var _usePathname;
|
|
40
|
+
const t = useT('shell');
|
|
41
|
+
const pathname = (_usePathname = usePathname()) != null ? _usePathname : '/';
|
|
42
|
+
const items = buildCrumbs(pathname, labels, t('breadcrumbs.home'));
|
|
43
|
+
return /*#__PURE__*/ _jsx(Breadcrumbs, {
|
|
44
|
+
items: items,
|
|
45
|
+
renderLink: (item)=>/*#__PURE__*/ _jsx(LocaleLink, {
|
|
46
|
+
href: item.href,
|
|
47
|
+
className: item.className,
|
|
48
|
+
children: item.label
|
|
49
|
+
})
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=breadcrumbs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/back-office/breadcrumbs.tsx"],"sourcesContent":["'use client';\n\nimport { splitLocalePath } from '@entifix/core';\nimport {\n type BreadcrumbItem,\n Breadcrumbs,\n useT,\n} from '@entifix/react-controls';\nimport { usePathname } from 'next/navigation';\n\nimport { LocaleLink } from '../i18n/index.js';\n\nexport interface BackOfficeBreadcrumbsProps {\n /** Map a path segment to an already-translated label; unmapped segments are\n * title-cased. Hosts resolve these through `useT` — the shell has no way to\n * know which namespace an app keeps its route names in. */\n labels?: Record<string, string>;\n}\n\nfunction humanize(segment: string): string {\n return segment.replace(/-/g, ' ').replace(/\\b\\w/g, c => c.toUpperCase());\n}\n\n/** Derives the crumb trail from a pathname. Exported for unit testing. */\nexport function buildCrumbs(\n pathname: string,\n labels: Record<string, string>,\n homeLabel: string,\n): BreadcrumbItem[] {\n const crumbs: BreadcrumbItem[] = [{ label: homeLabel, href: '/' }];\n let href = '';\n // The locale prefix is routing, not a place — a crumb reading \"Es\" would be\n // both meaningless and un-navigable.\n const { rest } = splitLocalePath(pathname);\n for (const segment of rest.split('/').filter(Boolean)) {\n href += `/${segment}`;\n crumbs.push({ label: labels[segment] ?? humanize(segment), href });\n }\n // The last crumb is the current page: drop its href so it renders as such.\n const last = crumbs[crumbs.length - 1];\n last.href = undefined;\n return crumbs;\n}\n\n/**\n * The root crumb is the shell's own copy: it names the shell's `/`, not\n * anything the host app authored. Apps used to pass their brand here\n * (\"Admin\", \"Identidad\"), which duplicated what the sidebar already shows.\n */\nexport function BackOfficeBreadcrumbs({\n labels = {},\n}: BackOfficeBreadcrumbsProps) {\n const t = useT('shell');\n const pathname = usePathname() ?? '/';\n const items = buildCrumbs(pathname, labels, t('breadcrumbs.home'));\n\n return (\n <Breadcrumbs\n items={items}\n renderLink={item => (\n <LocaleLink href={item.href} className={item.className}>\n {item.label}\n </LocaleLink>\n )}\n />\n );\n}\n"],"names":["splitLocalePath","Breadcrumbs","useT","usePathname","LocaleLink","humanize","segment","replace","c","toUpperCase","buildCrumbs","pathname","labels","homeLabel","crumbs","label","href","rest","split","filter","Boolean","push","last","length","undefined","BackOfficeBreadcrumbs","t","items","renderLink","item","className"],"mappings":"AAAA;;AAEA,SAASA,eAAe,QAAQ,gBAAgB;AAChD,SAEEC,WAAW,EACXC,IAAI,QACC,0BAA0B;AACjC,SAASC,WAAW,QAAQ,kBAAkB;AAE9C,SAASC,UAAU,QAAQ,mBAAmB;AAS9C,SAASC,SAASC,OAAe;IAC/B,OAAOA,QAAQC,OAAO,CAAC,MAAM,KAAKA,OAAO,CAAC,SAASC,CAAAA,IAAKA,EAAEC,WAAW;AACvE;AAEA,wEAAwE,GACxE,OAAO,SAASC,YACdC,QAAgB,EAChBC,MAA8B,EAC9BC,SAAiB;IAEjB,MAAMC,SAA2B;QAAC;YAAEC,OAAOF;YAAWG,MAAM;QAAI;KAAE;IAClE,IAAIA,OAAO;IACX,4EAA4E;IAC5E,qCAAqC;IACrC,MAAM,EAAEC,IAAI,EAAE,GAAGjB,gBAAgBW;IACjC,KAAK,MAAML,WAAWW,KAAKC,KAAK,CAAC,KAAKC,MAAM,CAACC,SAAU;YAEhCR;QADrBI,QAAQ,CAAC,CAAC,EAAEV,SAAS;QACrBQ,OAAOO,IAAI,CAAC;YAAEN,KAAK,GAAEH,kBAAAA,MAAM,CAACN,QAAQ,YAAfM,kBAAmBP,SAASC;YAAUU;QAAK;IAClE;IACA,2EAA2E;IAC3E,MAAMM,OAAOR,MAAM,CAACA,OAAOS,MAAM,GAAG,EAAE;IACtCD,KAAKN,IAAI,GAAGQ;IACZ,OAAOV;AACT;AAEA;;;;CAIC,GACD,OAAO,SAASW,sBAAsB,EACpCb,SAAS,CAAC,CAAC,EACgB;QAEVT;IADjB,MAAMuB,IAAIxB,KAAK;IACf,MAAMS,YAAWR,eAAAA,yBAAAA,eAAiB;IAClC,MAAMwB,QAAQjB,YAAYC,UAAUC,QAAQc,EAAE;IAE9C,qBACE,KAACzB;QACC0B,OAAOA;QACPC,YAAYC,CAAAA,qBACV,KAACzB;gBAAWY,MAAMa,KAAKb,IAAI;gBAAEc,WAAWD,KAAKC,SAAS;0BACnDD,KAAKd,KAAK;;;AAKrB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { NavSection, NavTier } from './nav.js';
|
|
2
|
+
/**
|
|
3
|
+
* Group sections into the sidebar's top tier — the screen type — preserving the
|
|
4
|
+
* order sections were contributed in within each group.
|
|
5
|
+
*
|
|
6
|
+
* The tier is the **type** and the domain sits beneath it (ADR 0033). Four fixed
|
|
7
|
+
* entries against eleven domains, so "where do I go to add a courier" has one
|
|
8
|
+
* answer whoever owns couriers; the daily operator's speed is the command
|
|
9
|
+
* palette's job rather than the sidebar's.
|
|
10
|
+
*
|
|
11
|
+
* Adjacent sections are **not** merged blindly — a host concatenates fragments
|
|
12
|
+
* from several shells, and two shells can legitimately contribute `master`
|
|
13
|
+
* sections that are not adjacent in the list. Grouping by rank rather than by
|
|
14
|
+
* position is what keeps Definiciones one heading instead of three.
|
|
15
|
+
*
|
|
16
|
+
* There is no third level: a `NavItem` has no children, so the depth cap lives
|
|
17
|
+
* in the type rather than in a convention. An arbitrary tree scans badly and
|
|
18
|
+
* rots, and every case ADR 0022's eleven domains present fits three tiers.
|
|
19
|
+
*/
|
|
20
|
+
export declare function groupByScreenType(sections: NavSection[]): NavTier[];
|
|
21
|
+
//# sourceMappingURL=group-by-screen-type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"group-by-screen-type.d.ts","sourceRoot":"","sources":["../../../src/lib/back-office/group-by-screen-type.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,EAAE,CAenE"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { screenTypeRank } from '@entifix/authz';
|
|
2
|
+
/**
|
|
3
|
+
* Group sections into the sidebar's top tier — the screen type — preserving the
|
|
4
|
+
* order sections were contributed in within each group.
|
|
5
|
+
*
|
|
6
|
+
* The tier is the **type** and the domain sits beneath it (ADR 0033). Four fixed
|
|
7
|
+
* entries against eleven domains, so "where do I go to add a courier" has one
|
|
8
|
+
* answer whoever owns couriers; the daily operator's speed is the command
|
|
9
|
+
* palette's job rather than the sidebar's.
|
|
10
|
+
*
|
|
11
|
+
* Adjacent sections are **not** merged blindly — a host concatenates fragments
|
|
12
|
+
* from several shells, and two shells can legitimately contribute `master`
|
|
13
|
+
* sections that are not adjacent in the list. Grouping by rank rather than by
|
|
14
|
+
* position is what keeps Definiciones one heading instead of three.
|
|
15
|
+
*
|
|
16
|
+
* There is no third level: a `NavItem` has no children, so the depth cap lives
|
|
17
|
+
* in the type rather than in a convention. An arbitrary tree scans badly and
|
|
18
|
+
* rots, and every case ADR 0022's eleven domains present fits three tiers.
|
|
19
|
+
*/ export function groupByScreenType(sections) {
|
|
20
|
+
const tiers = [];
|
|
21
|
+
for (const section of sections){
|
|
22
|
+
const tier = tiers.find((candidate)=>candidate.type === section.type);
|
|
23
|
+
if (tier === undefined) {
|
|
24
|
+
tiers.push({
|
|
25
|
+
type: section.type,
|
|
26
|
+
sections: [
|
|
27
|
+
section
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
tier.sections.push(section);
|
|
33
|
+
}
|
|
34
|
+
// An untyped section sorts last — it is not a screen group, so it belongs
|
|
35
|
+
// below the ones that are, never interleaved with them.
|
|
36
|
+
return tiers.sort((a, b)=>screenTypeRank(a.type) - screenTypeRank(b.type));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=group-by-screen-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/back-office/group-by-screen-type.ts"],"sourcesContent":["import { screenTypeRank } from '@entifix/authz';\n\nimport type { NavSection, NavTier } from './nav.js';\n\n/**\n * Group sections into the sidebar's top tier — the screen type — preserving the\n * order sections were contributed in within each group.\n *\n * The tier is the **type** and the domain sits beneath it (ADR 0033). Four fixed\n * entries against eleven domains, so \"where do I go to add a courier\" has one\n * answer whoever owns couriers; the daily operator's speed is the command\n * palette's job rather than the sidebar's.\n *\n * Adjacent sections are **not** merged blindly — a host concatenates fragments\n * from several shells, and two shells can legitimately contribute `master`\n * sections that are not adjacent in the list. Grouping by rank rather than by\n * position is what keeps Definiciones one heading instead of three.\n *\n * There is no third level: a `NavItem` has no children, so the depth cap lives\n * in the type rather than in a convention. An arbitrary tree scans badly and\n * rots, and every case ADR 0022's eleven domains present fits three tiers.\n */\nexport function groupByScreenType(sections: NavSection[]): NavTier[] {\n const tiers: NavTier[] = [];\n\n for (const section of sections) {\n const tier = tiers.find(candidate => candidate.type === section.type);\n if (tier === undefined) {\n tiers.push({ type: section.type, sections: [section] });\n continue;\n }\n tier.sections.push(section);\n }\n\n // An untyped section sorts last — it is not a screen group, so it belongs\n // below the ones that are, never interleaved with them.\n return tiers.sort((a, b) => screenTypeRank(a.type) - screenTypeRank(b.type));\n}\n"],"names":["screenTypeRank","groupByScreenType","sections","tiers","section","tier","find","candidate","type","undefined","push","sort","a","b"],"mappings":"AAAA,SAASA,cAAc,QAAQ,iBAAiB;AAIhD;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASC,kBAAkBC,QAAsB;IACtD,MAAMC,QAAmB,EAAE;IAE3B,KAAK,MAAMC,WAAWF,SAAU;QAC9B,MAAMG,OAAOF,MAAMG,IAAI,CAACC,CAAAA,YAAaA,UAAUC,IAAI,KAAKJ,QAAQI,IAAI;QACpE,IAAIH,SAASI,WAAW;YACtBN,MAAMO,IAAI,CAAC;gBAAEF,MAAMJ,QAAQI,IAAI;gBAAEN,UAAU;oBAACE;iBAAQ;YAAC;YACrD;QACF;QACAC,KAAKH,QAAQ,CAACQ,IAAI,CAACN;IACrB;IAEA,0EAA0E;IAC1E,wDAAwD;IACxD,OAAOD,MAAMQ,IAAI,CAAC,CAACC,GAAGC,IAAMb,eAAeY,EAAEJ,IAAI,IAAIR,eAAea,EAAEL,IAAI;AAC5E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/back-office/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/back-office/index.ts"],"sourcesContent":["export * from './account-menu.js';\nexport * from './back-office-shell.js';\nexport * from './breadcrumbs.js';\nexport * from './nav.js';\nexport * from './sidebar-nav.js';\n"],"names":[],"mappings":"AAAA,cAAc,oBAAoB;AAClC,cAAc,yBAAyB;AACvC,cAAc,mBAAmB;AACjC,cAAc,WAAW;AACzB,cAAc,mBAAmB"}
|