@owlmeans/client-panel 0.1.18-rc.25 → 0.1.18-rc.27
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/README.md +3 -2
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/client-panel/SKILL.md +7 -3
- package/build/components/nav/helper.d.ts.map +1 -1
- package/build/components/nav/helper.js +7 -8
- package/build/components/nav/helper.js.map +1 -1
- package/build/components/nav/types.d.ts +2 -3
- package/build/components/nav/types.d.ts.map +1 -1
- package/build/i18n.d.ts +2 -0
- package/build/i18n.d.ts.map +1 -0
- package/build/i18n.js +14 -0
- package/build/i18n.js.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/package.json +14 -14
- package/src/components/nav/helper.ts +7 -9
- package/src/components/nav/types.ts +2 -3
- package/src/i18n.ts +15 -0
- package/src/index.ts +2 -0
package/README.md
CHANGED
|
@@ -26,12 +26,13 @@ A complete form with submit and cancel actions:
|
|
|
26
26
|
```typescript
|
|
27
27
|
import { ClientForm, InputCtrl, ActionCtrl, useFormRef } from '@owlmeans/client-panel'
|
|
28
28
|
import type { FormOnSubmit } from '@owlmeans/client-panel'
|
|
29
|
+
import { appEntrypoints } from 'my-app-common'
|
|
29
30
|
|
|
30
31
|
function CreateProjectForm() {
|
|
31
32
|
const formRef = useFormRef()
|
|
32
33
|
|
|
33
34
|
const onSubmit: FormOnSubmit<CreateProject> = async (data) => {
|
|
34
|
-
await ctx.entrypoint
|
|
35
|
+
await ctx.entrypoint(appEntrypoints.api.projectCreate).call({ body: data })
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
return (
|
|
@@ -152,7 +153,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
152
153
|
your project's skill store (`.agents/skills/`):
|
|
153
154
|
|
|
154
155
|
```sh
|
|
155
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
156
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.16
|
|
156
157
|
```
|
|
157
158
|
|
|
158
159
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/client-panel",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-09-
|
|
4
|
+
"version": "0.1.18-rc.27",
|
|
5
|
+
"generatedAt": "2026-09-12T12:32:46.379Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -8,13 +8,17 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/client-panel
|
|
9
9
|
|
|
10
10
|
**Layer:** Client
|
|
11
|
-
**Install:** `"@owlmeans/client-panel": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/client-panel": "^0.1.18-rc.27"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
## Key Exports
|
|
14
14
|
|
|
15
15
|
Everything below is a **root** export — this package has no `./components` or `./helpers`
|
|
16
16
|
subpath. Only auth is split out (see below).
|
|
17
17
|
|
|
18
|
+
Importing the root also registers the package-owned seven-language `client-panel` bundle. Its
|
|
19
|
+
generic `buttons.submit` fallback is always available after an application imports any root form
|
|
20
|
+
controller; apps may override it through their own `buttons` resource.
|
|
21
|
+
|
|
18
22
|
| Export | Description |
|
|
19
23
|
|--------|-------------|
|
|
20
24
|
| `ClientForm` | The form model: `react-hook-form` + an AJV resolver with `coerceTypes` and `ajv-formats`, publishing a `FormContext` and a loader toggle |
|
|
@@ -122,10 +126,10 @@ alias, or null), `active` (its section), `showSide`, `isSectionActive` / `isItem
|
|
|
122
126
|
first, then by longest prefix, so a detail screen under a listed one still belongs to its section.
|
|
123
127
|
A screen listed in no section resolves its section by walking `route.route.parent` upward.
|
|
124
128
|
- **`hrefOf` gives a menu entry a real URL**, resolved synchronously from
|
|
125
|
-
`context.entrypoint(
|
|
129
|
+
`context.entrypoint(protocol).path()` — a protocol composes its path from its own declaration and
|
|
126
130
|
its ancestors', so matching one is a lookup rather than a guess. It returns undefined for a path
|
|
127
131
|
carrying route parameters (`:id`) — there is no honest URL for a screen whose address is not
|
|
128
|
-
known yet.
|
|
132
|
+
known yet. A protocol the app never bound resolves to null and is skipped rather than taking the
|
|
129
133
|
menu down.
|
|
130
134
|
|
|
131
135
|
## Depends On
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../../src/components/nav/helper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../../../src/components/nav/helper.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAgB,aAAa,EAAmB,MAAM,YAAY,CAAA;AAE5G,uFAAuF;AACvF,eAAO,MAAM,mBAAmB,EAAE,YAAmD,CAAA;AAErF;;;GAGG;AACH,eAAO,MAAM,eAAe,UAAW,MAAM,KAAG,MAK/C,CAAA;AAED,eAAO,MAAM,eAAe,cACf,YAAY,SAAS,MAAM,GAAG,SAAS,OAAO,MAAM,UAAU,MAAM,KAC9E,MAAgE,CAAA;AAQnE;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,WAAY,cAAc,KAAG,aA6FpD,CAAA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import { aliasOf } from '@owlmeans/entrypoint';
|
|
3
2
|
import { useContext, useNavigate } from '@owlmeans/client';
|
|
4
3
|
/** Default resolver: no i18n, the caller's fallback wins. See {@link NavTranslate}. */
|
|
5
4
|
export const defaultNavTranslate = (_key, defaultValue) => defaultValue;
|
|
@@ -35,12 +34,12 @@ export const usePanelNav = (config) => {
|
|
|
35
34
|
const sections = config.sections
|
|
36
35
|
.filter(section => section.hidden !== true)
|
|
37
36
|
.map(section => ({ ...section, items: visibleItems(section) }));
|
|
38
|
-
const pathOf = (
|
|
37
|
+
const pathOf = (alias) => {
|
|
39
38
|
try {
|
|
40
|
-
return normalizePath(context.entrypoint(
|
|
39
|
+
return normalizePath(context.entrypoint(alias).path());
|
|
41
40
|
}
|
|
42
41
|
catch {
|
|
43
|
-
//
|
|
42
|
+
// A protocol the app never bound addresses nothing — it cannot be the current screen,
|
|
44
43
|
// and it must not take the menu down with it.
|
|
45
44
|
return null;
|
|
46
45
|
}
|
|
@@ -51,7 +50,7 @@ export const usePanelNav = (config) => {
|
|
|
51
50
|
const here = normalizePath(pathname);
|
|
52
51
|
const exact = all.find(item => pathOf(item.alias) === here);
|
|
53
52
|
if (exact != null) {
|
|
54
|
-
current =
|
|
53
|
+
current = exact.alias;
|
|
55
54
|
}
|
|
56
55
|
else {
|
|
57
56
|
// Longest prefix: a detail screen under a listed one still belongs to its section.
|
|
@@ -59,10 +58,10 @@ export const usePanelNav = (config) => {
|
|
|
59
58
|
.map(item => ({ item, path: pathOf(item.alias) }))
|
|
60
59
|
.filter((entry) => entry.path != null && entry.path !== '/' && here.startsWith(`${entry.path}/`))
|
|
61
60
|
.sort((a, b) => b.path.length - a.path.length)[0];
|
|
62
|
-
current = prefixed
|
|
61
|
+
current = prefixed?.item.alias ?? null;
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
|
-
const sectionOf = (alias) => alias == null ? null : sections.find(section => section.items.some(item =>
|
|
64
|
+
const sectionOf = (alias) => alias == null ? null : sections.find(section => section.items.some(item => item.alias === alias)) ?? null;
|
|
66
65
|
let active = sectionOf(current);
|
|
67
66
|
if (active == null && current != null) {
|
|
68
67
|
// The current screen is not listed anywhere — walk up to the ancestor that is, so a
|
|
@@ -84,7 +83,7 @@ export const usePanelNav = (config) => {
|
|
|
84
83
|
}
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
|
-
const isItemActive = (item) =>
|
|
86
|
+
const isItemActive = (item) => item.alias === current;
|
|
88
87
|
const isSectionActive = (section) => active != null && section.name === active.name;
|
|
89
88
|
return {
|
|
90
89
|
sections,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../../../src/components/nav/helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../../../src/components/nav/helper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ComponentType } from 'react';
|
|
2
|
-
import type { EntrypointTarget } from '@owlmeans/client';
|
|
3
2
|
/**
|
|
4
3
|
* One screen in the navigation — the second menu level.
|
|
5
4
|
*
|
|
@@ -7,7 +6,7 @@ import type { EntrypointTarget } from '@owlmeans/client';
|
|
|
7
6
|
* resolves it, and a path that changes shape stays correct everywhere it is rendered.
|
|
8
7
|
*/
|
|
9
8
|
export interface PanelNavItem {
|
|
10
|
-
alias:
|
|
9
|
+
alias: string;
|
|
11
10
|
/** Literal label. Absent, the label is resolved through `translate` and falls back to a humanized alias. */
|
|
12
11
|
label?: string;
|
|
13
12
|
Icon?: ComponentType<{
|
|
@@ -32,7 +31,7 @@ export interface PanelNavConfig {
|
|
|
32
31
|
}
|
|
33
32
|
/** A footer link: exactly one of `alias` (an entrypoint) or `href` (anything else). */
|
|
34
33
|
export interface PanelNavLink {
|
|
35
|
-
alias?:
|
|
34
|
+
alias?: string;
|
|
36
35
|
href?: string;
|
|
37
36
|
label?: string;
|
|
38
37
|
/** Open in a new tab. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/nav/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/nav/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAA;AAE1C;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,4GAA4G;IAC5G,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,+EAA+E;IAC/E,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,eAAe,EAAE,CAAA;CAC5B;AAED,uFAAuF;AACvF,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yBAAyB;IACzB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAAA;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,yEAAyE;IACzE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAA;IACjB,eAAe,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAA;IACtD,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAA;IAC7C,SAAS,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,MAAM,IAAI,CAAA;IACnD,MAAM,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,IAAI,CAAA;IAC1C;;;;;;;OAOG;IACH,MAAM,EAAE,CAAC,MAAM,EAAE,YAAY,GAAG,eAAe,KAAK,MAAM,GAAG,SAAS,CAAA;CACvE"}
|
package/build/i18n.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":""}
|
package/build/i18n.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { addI18nLib } from '@owlmeans/i18n';
|
|
2
|
+
const buttons = {
|
|
3
|
+
en: { buttons: { submit: 'Submit' } },
|
|
4
|
+
pl: { buttons: { submit: 'Wyślij' } },
|
|
5
|
+
ru: { buttons: { submit: 'Отправить' } },
|
|
6
|
+
be: { buttons: { submit: 'Адправіць' } },
|
|
7
|
+
uk: { buttons: { submit: 'Надіслати' } },
|
|
8
|
+
es: { buttons: { submit: 'Enviar' } },
|
|
9
|
+
de: { buttons: { submit: 'Senden' } },
|
|
10
|
+
};
|
|
11
|
+
for (const [language, values] of Object.entries(buttons)) {
|
|
12
|
+
addI18nLib(language, 'client-panel', values);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE3C,MAAM,OAAO,GAAG;IACd,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;IACrC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;IACrC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE;IACxC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE;IACxC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE;IACxC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;IACrC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;CAC7B,CAAA;AAEV,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IACzD,UAAU,CAAC,QAAQ,EAAE,cAAc,EAAE,MAAM,CAAC,CAAA;AAC9C,CAAC"}
|
package/build/index.d.ts
CHANGED
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,WAAW,CAAA;AAEzB,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA"}
|
package/build/index.js
CHANGED
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,WAAW,CAAA;AAEzB,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/client-panel",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.27",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -36,19 +36,19 @@
|
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@hookform/resolvers": "^5.2.2",
|
|
39
|
-
"@owlmeans/client": "^0.1.18-rc.
|
|
40
|
-
"@owlmeans/client-i18n": "^0.1.18-rc.
|
|
41
|
-
"@owlmeans/client-entrypoint": "^0.1.18-rc.
|
|
42
|
-
"@owlmeans/client-route": "^0.1.18-rc.
|
|
43
|
-
"@owlmeans/error": "^0.1.18-rc.
|
|
44
|
-
"@owlmeans/entrypoint": "^0.1.18-rc.
|
|
39
|
+
"@owlmeans/client": "^0.1.18-rc.20",
|
|
40
|
+
"@owlmeans/client-i18n": "^0.1.18-rc.19",
|
|
41
|
+
"@owlmeans/client-entrypoint": "^0.1.18-rc.17",
|
|
42
|
+
"@owlmeans/client-route": "^0.1.18-rc.17",
|
|
43
|
+
"@owlmeans/error": "^0.1.18-rc.12",
|
|
44
|
+
"@owlmeans/entrypoint": "^0.1.18-rc.15"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@owlmeans/auth": "^0.1.18-rc.
|
|
48
|
-
"@owlmeans/client-auth": "^0.1.18-rc.
|
|
49
|
-
"@owlmeans/config": "^0.1.18-rc.
|
|
50
|
-
"@owlmeans/i18n": "^0.1.18-rc.
|
|
51
|
-
"@owlmeans/router": "^0.1.18-rc.
|
|
47
|
+
"@owlmeans/auth": "^0.1.18-rc.13",
|
|
48
|
+
"@owlmeans/client-auth": "^0.1.18-rc.24",
|
|
49
|
+
"@owlmeans/config": "^0.1.18-rc.16",
|
|
50
|
+
"@owlmeans/i18n": "^0.1.18-rc.12",
|
|
51
|
+
"@owlmeans/router": "^0.1.18-rc.12",
|
|
52
52
|
"ajv": "*",
|
|
53
53
|
"react": "*",
|
|
54
54
|
"react-hook-form": "*"
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@owlmeans/dep-config": "workspace:*",
|
|
66
|
-
"@owlmeans/auth": "^0.1.18-rc.
|
|
67
|
-
"@owlmeans/client-auth": "^0.1.18-rc.
|
|
66
|
+
"@owlmeans/auth": "^0.1.18-rc.13",
|
|
67
|
+
"@owlmeans/client-auth": "^0.1.18-rc.24",
|
|
68
68
|
"@types/react": "^19.2.17",
|
|
69
69
|
"nodemon": "^3.1.14",
|
|
70
70
|
"react-hook-form": "^7.53.0",
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
2
|
import type { ClientRoute } from '@owlmeans/client-route'
|
|
3
3
|
import type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
|
|
4
|
-
import { aliasOf } from '@owlmeans/entrypoint'
|
|
5
|
-
import type { EntrypointTarget } from '@owlmeans/client'
|
|
6
4
|
import type { Location } from '@owlmeans/router'
|
|
7
5
|
import { useContext, useNavigate } from '@owlmeans/client'
|
|
8
6
|
|
|
@@ -55,11 +53,11 @@ export const usePanelNav = (config: PanelNavConfig): PanelNavModel => {
|
|
|
55
53
|
.filter(section => section.hidden !== true)
|
|
56
54
|
.map(section => ({ ...section, items: visibleItems(section) }))
|
|
57
55
|
|
|
58
|
-
const pathOf = (
|
|
56
|
+
const pathOf = (alias: string): string | null => {
|
|
59
57
|
try {
|
|
60
|
-
return normalizePath(context.entrypoint<ClientEntrypoint<string>>(
|
|
58
|
+
return normalizePath(context.entrypoint<ClientEntrypoint<string>>(alias).path())
|
|
61
59
|
} catch {
|
|
62
|
-
//
|
|
60
|
+
// A protocol the app never bound addresses nothing — it cannot be the current screen,
|
|
63
61
|
// and it must not take the menu down with it.
|
|
64
62
|
return null
|
|
65
63
|
}
|
|
@@ -72,7 +70,7 @@ export const usePanelNav = (config: PanelNavConfig): PanelNavModel => {
|
|
|
72
70
|
const here = normalizePath(pathname)
|
|
73
71
|
const exact = all.find(item => pathOf(item.alias) === here)
|
|
74
72
|
if (exact != null) {
|
|
75
|
-
current =
|
|
73
|
+
current = exact.alias
|
|
76
74
|
} else {
|
|
77
75
|
// Longest prefix: a detail screen under a listed one still belongs to its section.
|
|
78
76
|
const prefixed = all
|
|
@@ -80,12 +78,12 @@ export const usePanelNav = (config: PanelNavConfig): PanelNavModel => {
|
|
|
80
78
|
.filter((entry): entry is { item: PanelNavItem, path: string } =>
|
|
81
79
|
entry.path != null && entry.path !== '/' && here.startsWith(`${entry.path}/`))
|
|
82
80
|
.sort((a, b) => b.path.length - a.path.length)[0]
|
|
83
|
-
current = prefixed
|
|
81
|
+
current = prefixed?.item.alias ?? null
|
|
84
82
|
}
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
const sectionOf = (alias: string | null): PanelNavSection | null =>
|
|
88
|
-
alias == null ? null : sections.find(section => section.items.some(item =>
|
|
86
|
+
alias == null ? null : sections.find(section => section.items.some(item => item.alias === alias)) ?? null
|
|
89
87
|
|
|
90
88
|
let active = sectionOf(current)
|
|
91
89
|
if (active == null && current != null) {
|
|
@@ -108,7 +106,7 @@ export const usePanelNav = (config: PanelNavConfig): PanelNavModel => {
|
|
|
108
106
|
}
|
|
109
107
|
}
|
|
110
108
|
|
|
111
|
-
const isItemActive = (item: PanelNavItem): boolean =>
|
|
109
|
+
const isItemActive = (item: PanelNavItem): boolean => item.alias === current
|
|
112
110
|
const isSectionActive = (section: PanelNavSection): boolean =>
|
|
113
111
|
active != null && section.name === active.name
|
|
114
112
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ComponentType } from 'react'
|
|
2
|
-
import type { EntrypointTarget } from '@owlmeans/client'
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* One screen in the navigation — the second menu level.
|
|
@@ -8,7 +7,7 @@ import type { EntrypointTarget } from '@owlmeans/client'
|
|
|
8
7
|
* resolves it, and a path that changes shape stays correct everywhere it is rendered.
|
|
9
8
|
*/
|
|
10
9
|
export interface PanelNavItem {
|
|
11
|
-
alias:
|
|
10
|
+
alias: string
|
|
12
11
|
/** Literal label. Absent, the label is resolved through `translate` and falls back to a humanized alias. */
|
|
13
12
|
label?: string
|
|
14
13
|
Icon?: ComponentType<{ className?: string }>
|
|
@@ -34,7 +33,7 @@ export interface PanelNavConfig {
|
|
|
34
33
|
|
|
35
34
|
/** A footer link: exactly one of `alias` (an entrypoint) or `href` (anything else). */
|
|
36
35
|
export interface PanelNavLink {
|
|
37
|
-
alias?:
|
|
36
|
+
alias?: string
|
|
38
37
|
href?: string
|
|
39
38
|
label?: string
|
|
40
39
|
/** Open in a new tab. */
|
package/src/i18n.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { addI18nLib } from '@owlmeans/i18n'
|
|
2
|
+
|
|
3
|
+
const buttons = {
|
|
4
|
+
en: { buttons: { submit: 'Submit' } },
|
|
5
|
+
pl: { buttons: { submit: 'Wyślij' } },
|
|
6
|
+
ru: { buttons: { submit: 'Отправить' } },
|
|
7
|
+
be: { buttons: { submit: 'Адправіць' } },
|
|
8
|
+
uk: { buttons: { submit: 'Надіслати' } },
|
|
9
|
+
es: { buttons: { submit: 'Enviar' } },
|
|
10
|
+
de: { buttons: { submit: 'Senden' } },
|
|
11
|
+
} as const
|
|
12
|
+
|
|
13
|
+
for (const [language, values] of Object.entries(buttons)) {
|
|
14
|
+
addI18nLib(language, 'client-panel', values)
|
|
15
|
+
}
|