@owlmeans/web-panel 0.1.18-rc.24 → 0.1.18-rc.26
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/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/web-panel/SKILL.md +11 -1
- package/build/auth/modules.d.ts +1 -1
- package/build/auth/modules.d.ts.map +1 -1
- package/build/components/login/screen.d.ts.map +1 -1
- package/build/components/login/screen.js +13 -1
- package/build/components/login/screen.js.map +1 -1
- package/build/components/login/terms.d.ts.map +1 -1
- package/build/components/login/terms.js +4 -1
- package/build/components/login/terms.js.map +1 -1
- package/build/modules.d.ts +1 -1
- package/build/modules.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/login/screen.tsx +17 -1
- package/src/components/login/terms.tsx +5 -2
- package/tests/login.spec.ts +41 -1
- package/build/.gitkeep +0 -0
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/web-panel",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-
|
|
4
|
+
"version": "0.1.18-rc.26",
|
|
5
|
+
"generatedAt": "2026-09-01T12:04:42.803Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -8,7 +8,7 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/web-panel
|
|
9
9
|
|
|
10
10
|
**Layer:** Web (React)
|
|
11
|
-
**Install:** `"@owlmeans/web-panel": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/web-panel": "^0.1.18-rc.26"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
## Key Exports
|
|
14
14
|
|
|
@@ -18,6 +18,7 @@ user-invocable: false
|
|
|
18
18
|
| `NavLayout` | The application shell — header, section menu, screen menu, content, footer |
|
|
19
19
|
| `TopNav` / `SideNav` / `Footer` | The shell's pieces, mountable on their own |
|
|
20
20
|
| `Toaster` | The application's toast surface — mounted once, in the layout |
|
|
21
|
+
| `LoginScreen` / `LocalizedLoginScreen` / `appendLoginScreen` | The identity-provider choice screen — see `login-methods` |
|
|
21
22
|
| `components` submodule | shadcn/Radix panel/form components |
|
|
22
23
|
| Re-exports from `@owlmeans/client-panel` | Cross-platform panel primitives, incl. `usePanelNav` and the `PanelNav*` types |
|
|
23
24
|
| `main`, `exports`, `context`, `modules`, `types` | Wiring helpers |
|
|
@@ -174,6 +175,15 @@ export const MainLayout: FC<PropsWithChildren> = ({ children }) => <>
|
|
|
174
175
|
- `sonner` is a dependency of this package, so nothing is required of the consumer — but an app
|
|
175
176
|
raising its own toasts should declare `sonner` too, at a range that resolves to the same copy.
|
|
176
177
|
|
|
178
|
+
## Subpath: `./consent`
|
|
179
|
+
|
|
180
|
+
`PanelCookieConsent` and `PanelCookiePolicy` — `@owlmeans/web-consent`'s components bound to this
|
|
181
|
+
app's language and translations, falling through to the package's own seven-language bundle for
|
|
182
|
+
every key the app has not overridden. See the `consent` skill.
|
|
183
|
+
|
|
184
|
+
A re-export does not move Tailwind class strings, so a consumer still adds an `@source` for
|
|
185
|
+
`@owlmeans/web-consent/build` as well as for this package's.
|
|
186
|
+
|
|
177
187
|
## Consumer setup — the `@` contract and Tailwind
|
|
178
188
|
|
|
179
189
|
`web-panel` emits `@/components/ui/*` and `@/lib/utils` verbatim; the app's bundler resolves `@` to
|
package/build/auth/modules.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const modules:
|
|
1
|
+
export declare const modules: any[];
|
|
2
2
|
//# sourceMappingURL=modules.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../../src/auth/modules.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../../src/auth/modules.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,OAAuB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/components/login/screen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAO/B,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAWhF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CA+
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/components/login/screen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAO/B,OAAO,KAAK,EAAe,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAWhF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CA+E5C,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,gBAAgB,CAOrD,CAAA"}
|
|
@@ -33,7 +33,19 @@ export const LoginScreen = props => {
|
|
|
33
33
|
...(props.methods != null ? { methods: props.methods } : {}),
|
|
34
34
|
});
|
|
35
35
|
const Logo = props.Logo;
|
|
36
|
-
|
|
36
|
+
// The viewport height is set INLINE, and deliberately.
|
|
37
|
+
//
|
|
38
|
+
// A percentage minimum (`min-h-full`) resolves against a parent that has a height, and this
|
|
39
|
+
// screen is rendered straight out of the dispatcher into whatever the app has around it — which
|
|
40
|
+
// almost never carries one, so the box collapsed to its content and the card sat at the top of
|
|
41
|
+
// an empty page. The fix is a viewport unit; the reason it is not a utility class is that this
|
|
42
|
+
// package's classes reach a consuming app's stylesheet only through a `@source` scan of its
|
|
43
|
+
// `src`, and a class NEW to that stylesheet is the one thing the scan can be stale about. Every
|
|
44
|
+
// other utility here already exists in any app that renders anything; a missing `min-h-dvh`
|
|
45
|
+
// rule, by contrast, is invisible — the screen looks nearly right and is silently uncentred.
|
|
46
|
+
//
|
|
47
|
+
// `props.style` still wins, because a class-based override no longer can.
|
|
48
|
+
return _jsx("div", { "data-login-screen": true, style: { minHeight: '100dvh', ...props.style }, className: cn('flex w-full items-center justify-center p-4', props.className), children: _jsxs(Card, { className: cn('w-full max-w-sm', props.containerClassName), children: [_jsxs(CardHeader, { className: "items-center gap-2 text-center", children: [Logo != null && _jsx("div", { className: "flex justify-center pb-2", children: isValidElement(Logo) ? Logo : typeof Logo === 'function'
|
|
37
49
|
? _jsx(Logo, { className: "h-10 w-auto" }) : Logo }), _jsx(CardTitle, { className: "text-xl", children: props.title ?? t('login.title', 'Sign in') }), _jsx(CardDescription, { children: props.subtitle ?? t('login.subtitle', 'Choose how you would like to continue.') })] }), _jsxs(CardContent, { className: "flex flex-col gap-4", children: [model.methods.length < 1
|
|
38
50
|
? _jsx("p", { role: "status", className: "text-sm text-muted-foreground text-center", children: t('login.empty', 'No sign-in method is configured for this application.') })
|
|
39
51
|
: _jsx("div", { className: "flex flex-col gap-2", children: model.methods.map((method) => _jsxs(Button, { type: "button", "data-login-method": method.id, variant: VARIANT[method.emphasis ?? 'secondary'] ?? 'outline', "aria-disabled": model.blocked, "data-blocked": model.blocked ? 'true' : undefined, className: cn('w-full justify-center gap-2', model.blocked && 'opacity-60'), autoFocus: method.id === model.primary?.id, onClick: () => model.select(method), children: [model.busy === method.id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../../../src/components/login/screen.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAChG,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAE7D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,OAAO,GAAmD;IAC9D,OAAO,EAAE,SAAS;IAClB,SAAS,EAAE,SAAS;IACpB,IAAI,EAAE,MAAM;CACb,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,WAAW,GAAyB,KAAK,CAAC,EAAE;IACvD,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC,IAAY,EAAE,YAAoB,EAAE,EAAE,CAAC,YAAY,CAAC,CAAA;IACnF,MAAM,KAAK,GAAG,eAAe,CAAC;QAC5B,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7D,CAAC,CAAA;IAEF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;IAEvB,OAAO,
|
|
1
|
+
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../../../src/components/login/screen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terms.d.ts","sourceRoot":"","sources":["../../../src/components/login/terms.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,OAAO,CAAA;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAElE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,eAAe,CAAA;IACtB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACxD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAuBD,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,
|
|
1
|
+
{"version":3,"file":"terms.d.ts","sourceRoot":"","sources":["../../../src/components/login/terms.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,OAAO,CAAA;AAE1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAElE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,eAAe,CAAA;IACtB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACxD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAuBD,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CA0C1C,CAAA"}
|
|
@@ -19,7 +19,10 @@ const interpolate = (sentence, slots) => sentence
|
|
|
19
19
|
});
|
|
20
20
|
export const LoginTerms = ({ model, translate, className }) => {
|
|
21
21
|
const link = (href, label) => _jsx("a", { href: href, target: "_blank", rel: "noreferrer noopener", className: "underline underline-offset-2 hover:text-foreground", children: label });
|
|
22
|
-
|
|
22
|
+
// Centred, like every other row in the card. The checkbox stays at the start of the sentence
|
|
23
|
+
// rather than above it, so `justify-center` centres the pair and `text-center` centres the
|
|
24
|
+
// wrapped lines within it.
|
|
25
|
+
return _jsxs("div", { className: cn('flex flex-col items-center gap-1.5 text-center', className), children: [_jsxs("label", { className: "flex items-start justify-center gap-2 text-sm text-muted-foreground cursor-pointer", children: [_jsx("input", { type: "checkbox", "data-login-terms": true, className: "mt-0.5 size-4 shrink-0 accent-primary", checked: model.accepted, "aria-invalid": model.attempted && !model.accepted, onChange: event => model.accept(event.target.checked) }), _jsx("span", { children: interpolate(translate('login.terms.agreement', 'I have read and agree to the {{terms}} and the {{privacy}}.'), {
|
|
23
26
|
terms: link(model.urls.terms, translate('login.terms.terms', 'Terms & Conditions')),
|
|
24
27
|
privacy: link(model.urls.privacy, translate('login.terms.privacy', 'Privacy Policy')),
|
|
25
28
|
cookies: model.urls.cookies != null
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terms.js","sourceRoot":"","sources":["../../../src/components/login/terms.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAShC;;;;;;;;GAQG;AACH,MAAM,WAAW,GAAG,CAClB,QAAgB,EAAE,KAAgC,EACrC,EAAE,CAAC,QAAQ;KACvB,KAAK,CAAC,mBAAmB,CAAC;KAC1B,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;IACnB,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAE9C,OAAO,KAAK,IAAI,IAAI;QAClB,CAAC,CAAC,yBAAmB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAA/B,KAAK,CAAkC;QACpD,CAAC,CAAC,yBAAmB,IAAI,IAAZ,KAAK,CAAe,CAAA;AACrC,CAAC,CAAC,CAAA;AAEJ,MAAM,CAAC,MAAM,UAAU,GAAwB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE;IACjF,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,KAAa,EAAa,EAAE,CACtD,YAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,EACtD,SAAS,EAAC,oDAAoD,YAAE,KAAK,GAAK,CAAA;IAE9E,OAAO,eAAK,SAAS,EAAE,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"terms.js","sourceRoot":"","sources":["../../../src/components/login/terms.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAShC;;;;;;;;GAQG;AACH,MAAM,WAAW,GAAG,CAClB,QAAgB,EAAE,KAAgC,EACrC,EAAE,CAAC,QAAQ;KACvB,KAAK,CAAC,mBAAmB,CAAC;KAC1B,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;IACnB,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAE9C,OAAO,KAAK,IAAI,IAAI;QAClB,CAAC,CAAC,yBAAmB,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAA/B,KAAK,CAAkC;QACpD,CAAC,CAAC,yBAAmB,IAAI,IAAZ,KAAK,CAAe,CAAA;AACrC,CAAC,CAAC,CAAA;AAEJ,MAAM,CAAC,MAAM,UAAU,GAAwB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE;IACjF,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,KAAa,EAAa,EAAE,CACtD,YAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,EACtD,SAAS,EAAC,oDAAoD,YAAE,KAAK,GAAK,CAAA;IAE9E,6FAA6F;IAC7F,2FAA2F;IAC3F,2BAA2B;IAC3B,OAAO,eAAK,SAAS,EAAE,EAAE,CAAC,gDAAgD,EAAE,SAAS,CAAC,aACpF,iBAAO,SAAS,EAAC,oFAAoF,aAOnG,gBACE,IAAI,EAAC,UAAU,4BACf,SAAS,EAAC,uCAAuC,EACjD,OAAO,EAAE,KAAK,CAAC,QAAQ,kBACT,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,EAChD,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GACrD,EACF,yBACG,WAAW,CACV,SAAS,CAAC,uBAAuB,EAC/B,6DAA6D,CAAC,EAChE;4BACE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,CAAC;4BACnF,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,qBAAqB,EAAE,gBAAgB,CAAC,CAAC;4BACrF,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI;gCACjC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,qBAAqB,EAAE,eAAe,CAAC,CAAC;gCAC7E,CAAC,CAAC,IAAI;yBACT,CACF,GACI,IACD,EACP,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,YAAG,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,0BAA0B,YACxF,SAAS,CAAC,sBAAsB,EAC/B,2EAA2E,CAAC,GAC5E,IACA,CAAA;AACR,CAAC,CAAA"}
|
package/build/modules.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const modules:
|
|
1
|
+
export declare const modules: any[];
|
|
2
2
|
//# sourceMappingURL=modules.d.ts.map
|
package/build/modules.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"modules.d.ts","sourceRoot":"","sources":["../src/modules.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,OAAO,OAAuB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/web-panel",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.26",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"@owlmeans/i18n": "^0.1.18-rc.6",
|
|
66
66
|
"@owlmeans/route": "^0.1.18-rc.6",
|
|
67
67
|
"@owlmeans/web-client": "^0.1.18-rc.18",
|
|
68
|
-
"@owlmeans/web-consent": "^0.1.18-rc.
|
|
68
|
+
"@owlmeans/web-consent": "^0.1.18-rc.4",
|
|
69
69
|
"@owlmeans/web-db": "^0.1.18-rc.10",
|
|
70
70
|
"@owlmeans/web-flow": "^0.1.18-rc.12",
|
|
71
71
|
"@owlmeans/web-router": "^0.1.18-rc.11",
|
|
@@ -38,7 +38,23 @@ export const LoginScreen: FC<LoginScreenProps> = props => {
|
|
|
38
38
|
|
|
39
39
|
const Logo = props.Logo
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
// The viewport height is set INLINE, and deliberately.
|
|
42
|
+
//
|
|
43
|
+
// A percentage minimum (`min-h-full`) resolves against a parent that has a height, and this
|
|
44
|
+
// screen is rendered straight out of the dispatcher into whatever the app has around it — which
|
|
45
|
+
// almost never carries one, so the box collapsed to its content and the card sat at the top of
|
|
46
|
+
// an empty page. The fix is a viewport unit; the reason it is not a utility class is that this
|
|
47
|
+
// package's classes reach a consuming app's stylesheet only through a `@source` scan of its
|
|
48
|
+
// `src`, and a class NEW to that stylesheet is the one thing the scan can be stale about. Every
|
|
49
|
+
// other utility here already exists in any app that renders anything; a missing `min-h-dvh`
|
|
50
|
+
// rule, by contrast, is invisible — the screen looks nearly right and is silently uncentred.
|
|
51
|
+
//
|
|
52
|
+
// `props.style` still wins, because a class-based override no longer can.
|
|
53
|
+
return <div
|
|
54
|
+
data-login-screen
|
|
55
|
+
style={{ minHeight: '100dvh', ...props.style }}
|
|
56
|
+
className={cn('flex w-full items-center justify-center p-4', props.className)}
|
|
57
|
+
>
|
|
42
58
|
<Card className={cn('w-full max-w-sm', props.containerClassName)}>
|
|
43
59
|
<CardHeader className="items-center gap-2 text-center">
|
|
44
60
|
{Logo != null && <div className="flex justify-center pb-2">
|
|
@@ -34,8 +34,11 @@ export const LoginTerms: FC<LoginTermsProps> = ({ model, translate, className })
|
|
|
34
34
|
<a href={href} target="_blank" rel="noreferrer noopener"
|
|
35
35
|
className="underline underline-offset-2 hover:text-foreground">{label}</a>
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
// Centred, like every other row in the card. The checkbox stays at the start of the sentence
|
|
38
|
+
// rather than above it, so `justify-center` centres the pair and `text-center` centres the
|
|
39
|
+
// wrapped lines within it.
|
|
40
|
+
return <div className={cn('flex flex-col items-center gap-1.5 text-center', className)}>
|
|
41
|
+
<label className="flex items-start justify-center gap-2 text-sm text-muted-foreground cursor-pointer">
|
|
39
42
|
{/*
|
|
40
43
|
A NATIVE checkbox, deliberately. `web-panel` ships no `checkbox` primitive, and requiring
|
|
41
44
|
every consumer to vendor one plus its Radix peer to render a sign-in screen would be a
|
package/tests/login.spec.ts
CHANGED
|
@@ -44,7 +44,47 @@ describe('@owlmeans/web-panel — the sign-in screen', () => {
|
|
|
44
44
|
const credit = await page.locator('[data-login-credit]').textContent()
|
|
45
45
|
expect(credit).toContain('Powered by OwlMeans')
|
|
46
46
|
expect(credit).toContain('Harness')
|
|
47
|
-
|
|
47
|
+
// A copyright NOTICE, not a name: the mark and the year are what make it one.
|
|
48
|
+
expect(credit).toContain(`© ${new Date().getFullYear()} Acme`)
|
|
49
|
+
} finally {
|
|
50
|
+
await close()
|
|
51
|
+
}
|
|
52
|
+
}, TIMEOUT)
|
|
53
|
+
|
|
54
|
+
test('centres the card in the viewport, rather than stacking it at the top', async () => {
|
|
55
|
+
const { page, close } = await open()
|
|
56
|
+
try {
|
|
57
|
+
const screen = await page.locator('[data-login-screen]').boundingBox()
|
|
58
|
+
const viewport = page.viewportSize()
|
|
59
|
+
|
|
60
|
+
// A percentage minimum height resolves against a parent that HAS a height, and the
|
|
61
|
+
// dispatcher renders this screen into a chain with none — so `min-h-full` collapsed the
|
|
62
|
+
// box to its content and left the card at the top of an otherwise empty page.
|
|
63
|
+
expect(screen?.height).toBeGreaterThanOrEqual((viewport?.height ?? 0) - 1)
|
|
64
|
+
|
|
65
|
+
// The height on its own is not the requirement — where the CARD ends up is. Asserted from
|
|
66
|
+
// the card's own centre so the test fails on a lost `items-center` too, not only on a lost
|
|
67
|
+
// height, and against the SCREEN box rather than the window because this harness mounts the
|
|
68
|
+
// screen inside the app shell, one header down. A dispatcher renders it as the whole page,
|
|
69
|
+
// where the two coincide.
|
|
70
|
+
const card = await page.locator('[data-login-screen] > *').first().boundingBox()
|
|
71
|
+
const cardCentre = (card?.y ?? 0) + (card?.height ?? 0) / 2
|
|
72
|
+
const screenCentre = (screen?.y ?? 0) + (screen?.height ?? 0) / 2
|
|
73
|
+
|
|
74
|
+
expect(Math.abs(cardCentre - screenCentre)).toBeLessThanOrEqual(2)
|
|
75
|
+
} finally {
|
|
76
|
+
await close()
|
|
77
|
+
}
|
|
78
|
+
}, TIMEOUT)
|
|
79
|
+
|
|
80
|
+
test('centres the terms confirmation, like every other row in the card', async () => {
|
|
81
|
+
const { page, close } = await open()
|
|
82
|
+
try {
|
|
83
|
+
const align = await page.locator('[data-login-terms]').evaluate(
|
|
84
|
+
node => window.getComputedStyle(node.closest('label') as Element).textAlign
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
expect(align).toBe('center')
|
|
48
88
|
} finally {
|
|
49
89
|
await close()
|
|
50
90
|
}
|
package/build/.gitkeep
DELETED
|
File without changes
|