@owlmeans/web-panel 0.1.18-rc.71 → 0.1.18-rc.73
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 +5 -3
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/web-panel/SKILL.md +57 -5
- package/build/components/login/i18n/be.json +10 -0
- package/build/components/login/i18n/de.json +10 -0
- package/build/components/login/i18n/en.json +10 -0
- package/build/components/login/i18n/es.json +10 -0
- package/build/components/login/i18n/fr.json +10 -0
- package/build/components/login/i18n/pl.json +10 -0
- package/build/components/login/i18n/ru.json +10 -0
- package/build/components/login/i18n/uk.json +10 -0
- package/build/components/login/i18n.d.ts +2 -0
- package/build/components/login/i18n.d.ts.map +1 -0
- package/build/components/login/i18n.js +28 -0
- package/build/components/login/i18n.js.map +1 -0
- package/build/components/login/index.d.ts +2 -0
- package/build/components/login/index.d.ts.map +1 -1
- package/build/components/login/index.js +2 -0
- package/build/components/login/index.js.map +1 -1
- package/build/components/login/provider.d.ts +20 -0
- package/build/components/login/provider.d.ts.map +1 -0
- package/build/components/login/provider.js +31 -0
- package/build/components/login/provider.js.map +1 -0
- package/build/components/login/screen.d.ts +1 -0
- package/build/components/login/screen.d.ts.map +1 -1
- package/build/components/login/screen.js +34 -14
- package/build/components/login/screen.js.map +1 -1
- package/build/components/login/types.d.ts +7 -2
- package/build/components/login/types.d.ts.map +1 -1
- package/build/consent/component.d.ts +4 -0
- package/build/consent/component.d.ts.map +1 -1
- package/build/consent/component.js +19 -5
- package/build/consent/component.js.map +1 -1
- package/build/consent/geo.d.ts +17 -0
- package/build/consent/geo.d.ts.map +1 -0
- package/build/consent/geo.js +19 -0
- package/build/consent/geo.js.map +1 -0
- package/build/consent/index.d.ts +4 -3
- package/build/consent/index.d.ts.map +1 -1
- package/build/consent/index.js +2 -1
- package/build/consent/index.js.map +1 -1
- package/build/consent/translate.js +1 -1
- package/build/consent/translate.js.map +1 -1
- package/build/consent/types.d.ts +20 -0
- package/build/consent/types.d.ts.map +1 -1
- package/build/entrypoints.d.ts +1 -7
- package/build/entrypoints.d.ts.map +1 -1
- package/build/types.d.ts +3 -0
- package/build/types.d.ts.map +1 -1
- package/package.json +23 -23
- package/src/components/login/i18n/be.json +10 -0
- package/src/components/login/i18n/de.json +10 -0
- package/src/components/login/i18n/en.json +10 -0
- package/src/components/login/i18n/es.json +10 -0
- package/src/components/login/i18n/fr.json +10 -0
- package/src/components/login/i18n/pl.json +10 -0
- package/src/components/login/i18n/ru.json +10 -0
- package/src/components/login/i18n/uk.json +10 -0
- package/src/components/login/i18n.ts +29 -0
- package/src/components/login/index.ts +3 -0
- package/src/components/login/provider.tsx +57 -0
- package/src/components/login/screen.tsx +107 -68
- package/src/components/login/types.ts +8 -2
- package/src/consent/component.tsx +30 -8
- package/src/consent/geo.ts +26 -0
- package/src/consent/index.ts +6 -2
- package/src/consent/translate.ts +1 -1
- package/src/consent/types.ts +22 -0
- package/src/types.ts +3 -0
- package/tests/consent.spec.ts +50 -0
- package/tests/harness/mount.tsx +60 -5
- package/tests/login-provider.spec.ts +114 -0
- package/tests/login.spec.ts +137 -0
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ but never started.
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
13
|
```sh
|
|
14
|
-
bun add @owlmeans/web-panel@^0.1.18-rc.
|
|
14
|
+
bun add @owlmeans/web-panel@^0.1.18-rc.73
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Peer requirements (the consuming app provides these): `react`, `react-dom`,
|
|
@@ -413,7 +413,9 @@ consumer's CSS puts dark tokens under `.dark` AND under
|
|
|
413
413
|
|
|
414
414
|
| Symbol | Kind | Purpose |
|
|
415
415
|
|---|---|---|
|
|
416
|
-
| `PanelCookieConsent`, `PanelCookiePolicy` | component | `@owlmeans/web-consent` components bound to the app's language and
|
|
416
|
+
| `PanelCookieConsent`, `PanelCookiePolicy` | component | `@owlmeans/web-consent` components bound to the app's language, translations and `cfg.cookieConsent` (`{ mode?, geo? }` — a prop wins) |
|
|
417
|
+
| `appendConsentGeoPlugin(ctx, plugin)` | function | Register the app's own country locator (`ConsentGeoPlugin`) while the context is configured; turns the geo gate on |
|
|
418
|
+
| `PanelCookieConsentConfig`, `ConsentGeoPluginAppend` | type | `cfg.cookieConsent`; the `context.consentGeo()` accessor |
|
|
417
419
|
| `PanelConsentMenuWidget` | component | The cookie-preferences control for a host menu or footer ("Cookie settings" — pass `label` and `className`) |
|
|
418
420
|
| `appendConsentWidgetService(ctx, alias?)`, `createConsentWidgetService` | function | Ref-counted presence service over a state resource |
|
|
419
421
|
| `useConsentMenuPresence()`, `useConsentWidgetPresent()` | hook | Declare that a menu shows the row; read whether one does (hides the floating button) |
|
|
@@ -496,7 +498,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
496
498
|
your project's skill store (`.agents/skills/`):
|
|
497
499
|
|
|
498
500
|
```sh
|
|
499
|
-
npx @owlmeans/agent-skills@^0.1.18-rc.
|
|
501
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.52
|
|
500
502
|
```
|
|
501
503
|
|
|
502
504
|
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/web-panel",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-10-
|
|
4
|
+
"version": "0.1.18-rc.73",
|
|
5
|
+
"generatedAt": "2026-10-08T21:27:54.321Z",
|
|
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.73"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
## Key Exports
|
|
14
14
|
|
|
@@ -21,6 +21,7 @@ user-invocable: false
|
|
|
21
21
|
| `ThemeToggle` / `useColorScheme` | The light/dark switcher (`ThemeToggleProps`, `ThemeToggleLabels`) and the hook behind it (`ColorSchemeModel`) — see *Light and dark* below |
|
|
22
22
|
| `SocketReloadDialog` | The global "connection lost — try again / reload" prompt (opt in via `cfg.socket.reloadDialog`) `PanelApp` mounts automatically — see below. The hooks it reads, `useSocketStatus` and `useSocketRetry`, are imported from `@owlmeans/client-socket`, not from this package |
|
|
23
23
|
| `Link` | An `<a>` addressing an entrypoint alias (or a literal `src`), with the label taken from i18n |
|
|
24
|
+
| `LoginProviderNote` | The provider disclosure (`LoginProviderNoteProps`) — see *The provider disclosure* below |
|
|
24
25
|
| `LoginScreen` / `LocalizedLoginScreen` / `appendLoginScreen` | The identity-provider choice screen — see `login-methods`. `LoginScreen` is pure w.r.t. `locale` too, exactly like `translate`: it is a prop, defaulting to nothing, never an implicit `useLanguage()` read, because a component that reaches for i18n context directly crashes an app mounted without one. `LocalizedLoginScreen` supplies `useLanguage()`'s value when the caller does not pass its own |
|
|
25
26
|
| `render(context, opts?)` | Mounts the tree inside `PanelApp`, with the browser language detector installed on the i18n instance. `opts` is `RenderOptions` plus `rootClassName` |
|
|
26
27
|
| `PanelApp` | That wrapper on its own — the themed root `div` plus the i18n provider — for a host that mounts the tree itself |
|
|
@@ -449,11 +450,60 @@ prop, never read from context directly — for `Intl.ListFormat` and a custom do
|
|
|
449
450
|
ordinary one, with no special case. Pinned by `tests/login.spec.ts` → the "with billing, product and
|
|
450
451
|
custom documents configured" and "the Terms confirmation deferred to a step" blocks.
|
|
451
452
|
|
|
453
|
+
### The provider disclosure — `LoginProviderNote`
|
|
454
|
+
|
|
455
|
+
`LoginScreen` renders `useLoginMethods().provider` (`@owlmeans/client-panel/auth`, resolution rules
|
|
456
|
+
there) through `components/login/provider.tsx`:
|
|
457
|
+
`<div role="note" data-login-provider data-placement="top|inline">` — a `ShieldCheck` icon, the
|
|
458
|
+
sentence, and, when `info` resolved, `<a data-login-provider-info target="_blank"
|
|
459
|
+
rel="noopener noreferrer">More information</a>`. Never a `header`/`nav`: it is a disclosure, not a
|
|
460
|
+
landmark.
|
|
461
|
+
|
|
462
|
+
- **No provider → the DOM is exactly the pre-provider screen** (no note, no stage, title
|
|
463
|
+
`login.title`).
|
|
464
|
+
- **`top`** (the platform's own hosts) — the strip is the FIRST child of `[data-login-screen]`,
|
|
465
|
+
full width, at the screen's top edge; the card sits in `<div data-login-stage>`, which takes the
|
|
466
|
+
remaining height and centres it. The screen's column layout, its zero padding, the stage's flex
|
|
467
|
+
centring/padding and the strip's width are INLINE styles (same reason as the screen height —
|
|
468
|
+
`login-methods` → Layout); classes there are cosmetic only.
|
|
469
|
+
- **`inline`** (an owner's own domain) — the note is one line inside `CardContent`, directly under
|
|
470
|
+
the methods and above the terms; the screen keeps its ordinary shape.
|
|
471
|
+
- The card title becomes `login.provider.title` ("Sign in to {{product}}") whenever a provider
|
|
472
|
+
resolves; `props.title` still wins.
|
|
473
|
+
- Copy: `login.provider.{title,top,inline,more}` in all eight languages
|
|
474
|
+
(`components/login/i18n/*.json`), registered by `components/login/i18n.ts` into the SAME `auth`
|
|
475
|
+
library resource as `client-auth`'s login copy (deep-merged; this package owns only the
|
|
476
|
+
`login.provider` subtree). Names are filled after translation by `loginProviderHelper.fill`.
|
|
477
|
+
- Still exactly one `[data-login-terms]` in either placement. Pinned by `tests/login.spec.ts` →
|
|
478
|
+
"the provider disclosure" (`?provider=top|inline` in the harness) and
|
|
479
|
+
`tests/login-provider.spec.ts` (resolver, `fill`, eight-language key/placeholder parity).
|
|
480
|
+
|
|
452
481
|
## Subpath: `./consent`
|
|
453
482
|
|
|
454
483
|
`PanelCookieConsent` and `PanelCookiePolicy` — `@owlmeans/web-consent`'s components bound to this
|
|
455
|
-
app's language and translations, falling through to the package's own
|
|
456
|
-
every key the app has not overridden
|
|
484
|
+
app's language and translations, falling through to the package's own eight-language bundle for
|
|
485
|
+
every key the app has not overridden — and to the app's cookie-consent configuration. See the
|
|
486
|
+
`consent` and `web-consent` skills.
|
|
487
|
+
|
|
488
|
+
**The configuration lives in `cfg.cookieConsent`** (`PanelCookieConsentConfig`, on `AppConfig`),
|
|
489
|
+
set where the rest of the app's configuration is, before anything renders:
|
|
490
|
+
|
|
491
|
+
```typescript
|
|
492
|
+
cfg.cookieConsent = { geo: { cloudflare: true } } // ask only in consent countries; mode: 'bar' default
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
- `mode` (`'bar'` | `'window'`) and `geo` (`ConsentGeoOptions`) feed both components; a prop of the
|
|
496
|
+
same name always wins. Not `cfg.consent` — "consent" also names the marketing-consent and sign-in
|
|
497
|
+
terms options.
|
|
498
|
+
- A file restored into apps of every age (a generated target's `config.ts`) writes it as
|
|
499
|
+
`Object.assign(cfg, { cookieConsent: … })`, so a tree whose framework predates the key still
|
|
500
|
+
type-checks; an older package ignores it.
|
|
501
|
+
- **A locator of the app's own** is code, not configuration: `appendConsentGeoPlugin(context,
|
|
502
|
+
plugin)` in `context.ts` registers a `ConsentGeoPlugin` (`{ alias, locate }` — resolve the country
|
|
503
|
+
or throw) ahead of Cloudflare's and installs `context.consentGeo()`. Appending one IS asking for
|
|
504
|
+
the gate: `PanelCookieConsent` turns it on (`geo: {}`) even where `cfg.cookieConsent.geo` says
|
|
505
|
+
nothing. `PanelCookiePolicy` reads the same, so the policy states the regional rule exactly when
|
|
506
|
+
the dialog applies it.
|
|
457
507
|
|
|
458
508
|
A re-export does not move Tailwind class strings, so a consumer adds a second `@source` for
|
|
459
509
|
`@owlmeans/web-consent` alongside this package's — pointing at **`src`**, for the reason spelled out
|
|
@@ -503,7 +553,8 @@ menu has already mounted) and because React 18 StrictMode double-invokes mount/c
|
|
|
503
553
|
|
|
504
554
|
| Job | Import from `@owlmeans/web-panel/consent` | Where it goes |
|
|
505
555
|
|---|---|---|
|
|
506
|
-
| The consent
|
|
556
|
+
| The consent UI — bar, window, spinner (and its floating re-open button) | `PanelCookieConsent` | Beside the router — a `PanelApp` child — once |
|
|
557
|
+
| Asking only in consent countries | `cfg.cookieConsent.geo`, or `appendConsentGeoPlugin(context, plugin)` | The app's `config.ts` / `context.ts` |
|
|
507
558
|
| The "Cookie settings" control in a footer or menu | `PanelConsentMenuWidget` (`label`, `className`, `onSelect?` — defaults to `consentStore.open('reopen')`) | Inside the host's own footer/menu |
|
|
508
559
|
| Hiding the floating button while that control is reachable | `useConsentMenuPresence()` | Called by the always-mounted component that renders the control — mounted ONLY while the control can actually be reached: a component that is merely hidden by CSS (`xl:hidden`) is still mounted and still claims presence, so the floating button vanishes with nothing else to open the dialog; render it conditionally instead (viable's header mounts its hamburger menu only below the full-row breakpoint) |
|
|
509
560
|
| Registering the presence service | `appendConsentWidgetService(context)` | The app's `context.ts` |
|
|
@@ -528,7 +579,8 @@ bound dialog with its floating button; `useConsentMenuPresence()` then has nothi
|
|
|
528
579
|
does nothing. The presence read itself (`useConsentWidgetPresent`) still needs the service — its
|
|
529
580
|
state resource is registered by it — so any other caller checks first. A dialog that read an
|
|
530
581
|
unregistered state resource threw inside render ("Resource consent-widget-presence not found") and
|
|
531
|
-
blanked the whole application. Pinned by `tests/consent.spec.ts` (`?consent=bare` / `?consent=menu
|
|
582
|
+
blanked the whole application. Pinned by `tests/consent.spec.ts` (`?consent=bare` / `?consent=menu`;
|
|
583
|
+
the configuration by `?consentCfg=window|bar`, `?modeProp=` and `?consentGeo=<CC>|fail`).
|
|
532
584
|
|
|
533
585
|
## Consumer setup — package boundary and Tailwind
|
|
534
586
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"provider": {
|
|
4
|
+
"title": "Уваход у {{product}}",
|
|
5
|
+
"top": "Гэтую праграму размяшчае {{operator}} ад імя {{product}}. Для ўваходу выкарыстоўваецца {{provider}}.",
|
|
6
|
+
"inline": "Уваход забяспечвае {{provider}} ад імя {{product}}.",
|
|
7
|
+
"more": "Падрабязней"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"provider": {
|
|
4
|
+
"title": "Bei {{product}} anmelden",
|
|
5
|
+
"top": "Diese App wird von {{operator}} im Auftrag von {{product}} gehostet. Sie melden sich mit {{provider}} an.",
|
|
6
|
+
"inline": "Die Anmeldung stellt {{provider}} im Auftrag von {{product}} bereit.",
|
|
7
|
+
"more": "Weitere Informationen"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"provider": {
|
|
4
|
+
"title": "Sign in to {{product}}",
|
|
5
|
+
"top": "This app is hosted by {{operator}} on behalf of {{product}}. You sign in with {{provider}}.",
|
|
6
|
+
"inline": "Sign-in is provided by {{provider}} on behalf of {{product}}.",
|
|
7
|
+
"more": "More information"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"provider": {
|
|
4
|
+
"title": "Iniciar sesión en {{product}}",
|
|
5
|
+
"top": "Esta aplicación está alojada por {{operator}} en nombre de {{product}}. Inicias sesión con {{provider}}.",
|
|
6
|
+
"inline": "El inicio de sesión lo proporciona {{provider}} en nombre de {{product}}.",
|
|
7
|
+
"more": "Más información"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"provider": {
|
|
4
|
+
"title": "Connexion à {{product}}",
|
|
5
|
+
"top": "Cette application est hébergée par {{operator}} pour le compte de {{product}}. Vous vous connectez avec {{provider}}.",
|
|
6
|
+
"inline": "La connexion est assurée par {{provider}} pour le compte de {{product}}.",
|
|
7
|
+
"more": "En savoir plus"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"provider": {
|
|
4
|
+
"title": "Zaloguj się do {{product}}",
|
|
5
|
+
"top": "Ta aplikacja jest hostowana przez {{operator}} w imieniu {{product}}. Logujesz się przez {{provider}}.",
|
|
6
|
+
"inline": "Logowanie zapewnia {{provider}} w imieniu {{product}}.",
|
|
7
|
+
"more": "Więcej informacji"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"provider": {
|
|
4
|
+
"title": "Вход в {{product}}",
|
|
5
|
+
"top": "Это приложение размещает {{operator}} от имени {{product}}. Для входа используется {{provider}}.",
|
|
6
|
+
"inline": "Вход обеспечивает {{provider}} от имени {{product}}.",
|
|
7
|
+
"more": "Подробнее"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"provider": {
|
|
4
|
+
"title": "Вхід до {{product}}",
|
|
5
|
+
"top": "Цей застосунок розміщує {{operator}} від імені {{product}}. Для входу використовується {{provider}}.",
|
|
6
|
+
"inline": "Вхід забезпечує {{provider}} від імені {{product}}.",
|
|
7
|
+
"more": "Докладніше"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../../src/components/login/i18n.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { i18nHelper } from '@owlmeans/i18n';
|
|
2
|
+
import en from './i18n/en.json' with { type: 'json' };
|
|
3
|
+
import pl from './i18n/pl.json' with { type: 'json' };
|
|
4
|
+
import ru from './i18n/ru.json' with { type: 'json' };
|
|
5
|
+
import be from './i18n/be.json' with { type: 'json' };
|
|
6
|
+
import uk from './i18n/uk.json' with { type: 'json' };
|
|
7
|
+
import es from './i18n/es.json' with { type: 'json' };
|
|
8
|
+
import de from './i18n/de.json' with { type: 'json' };
|
|
9
|
+
import fr from './i18n/fr.json' with { type: 'json' };
|
|
10
|
+
import { AUTH_RESOURCE } from './consts.local.js';
|
|
11
|
+
/**
|
|
12
|
+
* The provider disclosure's copy (`login.provider.*`), registered into the SAME `auth` library
|
|
13
|
+
* resource `@owlmeans/client-auth/login` fills with the rest of the sign-in screen.
|
|
14
|
+
*
|
|
15
|
+
* `_addI18n` pushes and the bundles are merged deeply by tier and priority, so this chunk lands
|
|
16
|
+
* beside `login.title`/`login.terms.*` rather than replacing the `login` subtree. It lives here, not
|
|
17
|
+
* in `client-auth`, because only this package renders the disclosure — and `client-auth` is pinned
|
|
18
|
+
* exactly by applications that must not be pulled into a release for it.
|
|
19
|
+
*/
|
|
20
|
+
i18nHelper.addI18nLib('en', AUTH_RESOURCE, en);
|
|
21
|
+
i18nHelper.addI18nLib('pl', AUTH_RESOURCE, pl);
|
|
22
|
+
i18nHelper.addI18nLib('ru', AUTH_RESOURCE, ru);
|
|
23
|
+
i18nHelper.addI18nLib('be', AUTH_RESOURCE, be);
|
|
24
|
+
i18nHelper.addI18nLib('uk', AUTH_RESOURCE, uk);
|
|
25
|
+
i18nHelper.addI18nLib('es', AUTH_RESOURCE, es);
|
|
26
|
+
i18nHelper.addI18nLib('de', AUTH_RESOURCE, de);
|
|
27
|
+
i18nHelper.addI18nLib('fr', AUTH_RESOURCE, fr);
|
|
28
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../../src/components/login/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,EAAE,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACrD,OAAO,EAAE,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACrD,OAAO,EAAE,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACrD,OAAO,EAAE,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACrD,OAAO,EAAE,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACrD,OAAO,EAAE,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACrD,OAAO,EAAE,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACrD,OAAO,EAAE,MAAM,gBAAgB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAEjD;;;;;;;;GAQG;AACH,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA;AAC9C,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA;AAC9C,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA;AAC9C,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA;AAC9C,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA;AAC9C,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA;AAC9C,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA;AAC9C,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAAC,CAAA"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import './i18n.js';
|
|
1
2
|
export * from './screen.js';
|
|
2
3
|
export * from './terms.js';
|
|
3
4
|
export type * from './types.js';
|
|
4
5
|
export * from './credit.js';
|
|
6
|
+
export * from './provider.js';
|
|
5
7
|
export * from './consts.js';
|
|
6
8
|
export * from './icons.js';
|
|
7
9
|
export * from './append.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/login/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,mBAAmB,YAAY,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/login/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAElB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,mBAAmB,YAAY,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/login/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/login/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,CAAA;AAElB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAE1B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import type { LoginProviderNoteProps } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Who signs the person in, and on whose behalf.
|
|
5
|
+
*
|
|
6
|
+
* A sign-in page that a third party runs for an application has to say so wherever the
|
|
7
|
+
* application's own name appears: the relationship in a sentence, and a "More information" link.
|
|
8
|
+
* Without it the page is a stranger's form wearing someone else's name — which is precisely what a
|
|
9
|
+
* browser's impersonation heuristics look for.
|
|
10
|
+
*
|
|
11
|
+
* `top` is a full-width strip the screen renders as its FIRST child, above the card (the platform's
|
|
12
|
+
* own hosts); `inline` is one line inside the card, under the methods (an owner's own domain).
|
|
13
|
+
* A `role="note"` block, never `header`/`nav`: it is a disclosure, not page chrome, and a screen
|
|
14
|
+
* that grew a landmark here would be read as a second banner.
|
|
15
|
+
*
|
|
16
|
+
* The names are put in after translation (`loginProviderHelper.fill`), so word order stays the
|
|
17
|
+
* translator's and nothing but plain text ever reaches the markup.
|
|
18
|
+
*/
|
|
19
|
+
export declare const LoginProviderNote: FC<LoginProviderNoteProps>;
|
|
20
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/components/login/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAI/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAExD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,sBAAsB,CAkCxD,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ShieldCheck } from 'lucide-react';
|
|
3
|
+
import { cn } from '../../@/lib/utils.js';
|
|
4
|
+
import { loginProviderHelper } from '@owlmeans/client-panel/auth';
|
|
5
|
+
/**
|
|
6
|
+
* Who signs the person in, and on whose behalf.
|
|
7
|
+
*
|
|
8
|
+
* A sign-in page that a third party runs for an application has to say so wherever the
|
|
9
|
+
* application's own name appears: the relationship in a sentence, and a "More information" link.
|
|
10
|
+
* Without it the page is a stranger's form wearing someone else's name — which is precisely what a
|
|
11
|
+
* browser's impersonation heuristics look for.
|
|
12
|
+
*
|
|
13
|
+
* `top` is a full-width strip the screen renders as its FIRST child, above the card (the platform's
|
|
14
|
+
* own hosts); `inline` is one line inside the card, under the methods (an owner's own domain).
|
|
15
|
+
* A `role="note"` block, never `header`/`nav`: it is a disclosure, not page chrome, and a screen
|
|
16
|
+
* that grew a landmark here would be read as a second banner.
|
|
17
|
+
*
|
|
18
|
+
* The names are put in after translation (`loginProviderHelper.fill`), so word order stays the
|
|
19
|
+
* translator's and nothing but plain text ever reaches the markup.
|
|
20
|
+
*/
|
|
21
|
+
export const LoginProviderNote = ({ model, translate, className }) => {
|
|
22
|
+
const top = model.placement === 'top';
|
|
23
|
+
const sentence = top
|
|
24
|
+
? translate('login.provider.top', 'This app is hosted by {{operator}} on behalf of {{product}}. You sign in with {{provider}}.')
|
|
25
|
+
: translate('login.provider.inline', 'Sign-in is provided by {{provider}} on behalf of {{product}}.');
|
|
26
|
+
return _jsxs("div", { role: "note", "data-login-provider": true, "data-placement": model.placement,
|
|
27
|
+
// The strip's full width is inline for the same reason the screen's height is: it is the part
|
|
28
|
+
// of the layout a stale `@source` scan must never be able to drop.
|
|
29
|
+
style: top ? { width: '100%', boxSizing: 'border-box' } : undefined, className: cn('flex items-start justify-center gap-2 text-center text-xs text-muted-foreground', top && 'border-b bg-muted px-4 py-2', className), children: [_jsx(ShieldCheck, { "aria-hidden": "true", className: "size-4 shrink-0" }), _jsxs("span", { children: [loginProviderHelper.fill(sentence, model), model.info != null && _jsxs(_Fragment, { children: [' ', _jsx("a", { "data-login-provider-info": true, href: model.info, target: "_blank", rel: "noopener noreferrer", className: "underline underline-offset-2 hover:text-foreground", children: translate('login.provider.more', 'More information') })] })] })] });
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/components/login/provider.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,EAAE,EAAE,MAAM,sBAAsB,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAGjE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA+B,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE;IAC/F,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,KAAK,KAAK,CAAA;IACrC,MAAM,QAAQ,GAAG,GAAG;QAClB,CAAC,CAAC,SAAS,CAAC,oBAAoB,EAAE,6FAA6F,CAAC;QAChI,CAAC,CAAC,SAAS,CAAC,uBAAuB,EAAE,+DAA+D,CAAC,CAAA;IAEvG,OAAO,eACL,IAAI,EAAC,MAAM,iDAEK,KAAK,CAAC,SAAS;QAC/B,8FAA8F;QAC9F,mEAAmE;QACnE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS,EACnE,SAAS,EAAE,EAAE,CACX,iFAAiF,EACjF,GAAG,IAAI,6BAA6B,EACpC,SAAS,CACV,aAED,KAAC,WAAW,mBAAa,MAAM,EAAC,SAAS,EAAC,iBAAiB,GAAG,EAC9D,2BACG,mBAAmB,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,EACzC,KAAK,CAAC,IAAI,IAAI,IAAI,IAAI,8BACpB,GAAG,EACJ,8CAEE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,EAC3D,SAAS,EAAC,oDAAoD,YAE7D,SAAS,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,GACnD,IACH,IACE,IACH,CAAA;AACR,CAAC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/components/login/screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAA;AAO/C,OAAO,EAAoB,KAAK,gBAAgB,EAAqB,MAAM,6BAA6B,CAAA;AAMxG;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/components/login/screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAA;AAO/C,OAAO,EAAoB,KAAK,gBAAgB,EAAqB,MAAM,6BAA6B,CAAA;AAMxG,OAAO,WAAW,CAAA;AAElB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAqI5C,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,gBAAgB,CASrD,CAAA"}
|
|
@@ -5,12 +5,14 @@ import { Button } from '../../@/components/ui/button.js';
|
|
|
5
5
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '../../@/components/ui/card.js';
|
|
6
6
|
import { cn } from '../../@/lib/utils.js';
|
|
7
7
|
import { useI18nLib, useLanguage } from '@owlmeans/client-i18n';
|
|
8
|
-
import { useLoginMethods } from '@owlmeans/client-panel/auth';
|
|
8
|
+
import { loginProviderHelper, useLoginMethods } from '@owlmeans/client-panel/auth';
|
|
9
9
|
import { loginResumeHelper } from '@owlmeans/client-auth/login';
|
|
10
10
|
import { LoginMethodIcon } from './icons.js';
|
|
11
11
|
import { LoginPrivacyNotice, LoginTerms } from './terms.js';
|
|
12
12
|
import { LoginCredit } from './credit.js';
|
|
13
|
+
import { LoginProviderNote } from './provider.js';
|
|
13
14
|
import { VARIANT } from './consts.local.js';
|
|
15
|
+
import './i18n.js';
|
|
14
16
|
/**
|
|
15
17
|
* The sign-in screen: which identity provider, confirmed against which documents.
|
|
16
18
|
*
|
|
@@ -31,6 +33,23 @@ export const LoginScreen = props => {
|
|
|
31
33
|
});
|
|
32
34
|
const Logo = props.Logo;
|
|
33
35
|
const attemptError = model.busy == null ? loginResumeHelper.loginAttemptError(model.outcome) : null;
|
|
36
|
+
const provider = model.provider;
|
|
37
|
+
const title = props.title ?? (provider != null
|
|
38
|
+
? loginProviderHelper.fill(t('login.provider.title', 'Sign in to {{product}}'), provider)
|
|
39
|
+
: t('login.title', 'Sign in'));
|
|
40
|
+
const card = _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'
|
|
41
|
+
? _jsx(Logo, { className: "h-10 w-auto" }) : Logo }), _jsx(CardTitle, { className: "text-xl", children: title }), _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
|
|
42
|
+
? _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.') })
|
|
43
|
+
: _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 || undefined, "data-blocked": model.blocked ? 'true' : undefined,
|
|
44
|
+
// `cursor-pointer` explicitly: the package's private shadcn button stays compatible
|
|
45
|
+
// with the older primitive style too. Stating it here keeps the sign-in control
|
|
46
|
+
// visibly actionable independently of a consumer's shadcn setup.
|
|
47
|
+
className: cn('w-full justify-center gap-2 cursor-pointer', model.blocked && 'opacity-60'), autoFocus: method.id === model.primary?.id, onClick: () => model.select(method), children: [model.busy === method.id
|
|
48
|
+
? _jsx(Loader2, { className: "size-4 animate-spin" })
|
|
49
|
+
: _jsx(LoginMethodIcon, { name: method.icon, className: "size-4" }), method.label ?? t(`login.method.${method.i18nKey ?? method.id}`, method.id)] }, method.id)) }), provider?.placement === 'inline' && _jsx(LoginProviderNote, { model: provider, translate: t }), model.terms.required && (model.terms.deferred
|
|
50
|
+
? _jsx(LoginPrivacyNotice, { model: model.terms, translate: t, locale: props.locale })
|
|
51
|
+
: _jsx(LoginTerms, { model: model.terms, translate: t, locale: props.locale })), (model.error ?? attemptError) != null
|
|
52
|
+
&& _jsx("p", { role: "alert", "data-login-error": true, className: "text-sm text-destructive text-center", children: model.error ?? t(attemptError, 'Sign-in did not complete. Please try again.') })] }), _jsx("div", { className: "px-6", children: props.footer ?? _jsx(LoginCredit, { model: model.credit, translate: t }) })] });
|
|
34
53
|
// The viewport height is set INLINE, and deliberately.
|
|
35
54
|
//
|
|
36
55
|
// A percentage minimum (`min-h-full`) resolves against a parent that has a height, and this
|
|
@@ -43,19 +62,20 @@ export const LoginScreen = props => {
|
|
|
43
62
|
// rule, by contrast, is invisible — the screen looks nearly right and is silently uncentred.
|
|
44
63
|
//
|
|
45
64
|
// `props.style` still wins, because a class-based override no longer can.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
//
|
|
66
|
+
// The platform's own hosts put the provider disclosure in a strip across the top of the page —
|
|
67
|
+
// the FIRST child of the screen — and centre the card in a stage that takes the rest of the
|
|
68
|
+
// height. Every layout-bearing property of that variant is inline too, for the same reason.
|
|
69
|
+
if (provider?.placement === 'top') {
|
|
70
|
+
return _jsxs("div", { "data-login-screen": true, style: {
|
|
71
|
+
minHeight: '100dvh', display: 'flex', flexDirection: 'column', alignItems: 'stretch',
|
|
72
|
+
justifyContent: 'flex-start', padding: 0, ...props.style,
|
|
73
|
+
}, className: cn('w-full', props.className), children: [_jsx(LoginProviderNote, { model: provider, translate: t }), _jsx("div", { "data-login-stage": true, style: {
|
|
74
|
+
display: 'flex', flex: '1 1 auto', alignItems: 'center', justifyContent: 'center',
|
|
75
|
+
width: '100%', padding: '1rem', boxSizing: 'border-box',
|
|
76
|
+
}, children: card })] });
|
|
77
|
+
}
|
|
78
|
+
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: card });
|
|
59
79
|
};
|
|
60
80
|
/**
|
|
61
81
|
* {@link LoginScreen} bound to the application's own translations.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../../../src/components/login/screen.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAW,MAAM,OAAO,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAA;AACxD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AACzG,OAAO,EAAE,EAAE,EAAE,MAAM,sBAAsB,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"screen.js","sourceRoot":"","sources":["../../../src/components/login/screen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LoginScreenProps } from '@owlmeans/client-auth/login';
|
|
2
2
|
import type { ComponentType, ReactNode } from 'react';
|
|
3
|
-
import type { LoginCreditModel, LoginTermsModel } from '@owlmeans/client-panel/auth';
|
|
3
|
+
import type { LoginCreditModel, LoginProviderModel, LoginTermsModel } from '@owlmeans/client-panel/auth';
|
|
4
4
|
export interface LoginScreenSetup extends Omit<LoginScreenProps, 'translate'> {
|
|
5
5
|
/** The one thing an application is expected to supply. */
|
|
6
6
|
Logo?: ComponentType<{
|
|
@@ -15,9 +15,14 @@ export interface LoginCreditProps {
|
|
|
15
15
|
export interface LoginTermsProps {
|
|
16
16
|
model: LoginTermsModel;
|
|
17
17
|
translate: (key: string, defaultValue: string) => string;
|
|
18
|
-
/** The current language, for `Intl.ListFormat
|
|
18
|
+
/** The current language, for `Intl.ListFormat`, document labels and explicit translated hrefs. */
|
|
19
19
|
locale?: string;
|
|
20
20
|
className?: string;
|
|
21
21
|
}
|
|
22
22
|
export type LoginPrivacyNoticeProps = LoginTermsProps;
|
|
23
|
+
export interface LoginProviderNoteProps {
|
|
24
|
+
model: LoginProviderModel;
|
|
25
|
+
translate: (key: string, defaultValue: string) => string;
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
23
28
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/login/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/login/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAExG,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,WAAW,CAAC;IAC3E,0DAA0D;IAC1D,IAAI,CAAC,EAAE,aAAa,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,SAAS,CAAA;CACzD;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,gBAAgB,CAAA;IACvB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACxD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,eAAe,CAAA;IACtB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACxD,kGAAkG;IAClG,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,MAAM,uBAAuB,GAAG,eAAe,CAAA;AAErD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,kBAAkB,CAAA;IACzB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACxD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB"}
|
|
@@ -19,5 +19,9 @@ import { type CookieConsentProps, type CookiePolicyProps } from '@owlmeans/web-c
|
|
|
19
19
|
* while the context is built, before anything renders.
|
|
20
20
|
*/
|
|
21
21
|
export declare const PanelCookieConsent: FC<CookieConsentProps>;
|
|
22
|
+
/**
|
|
23
|
+
* The cookie-policy page, bound like the dialog — and told about the geo gate the same way, so it
|
|
24
|
+
* states the regional rule exactly when the dialog applies it.
|
|
25
|
+
*/
|
|
22
26
|
export declare const PanelCookiePolicy: FC<CookiePolicyProps>;
|
|
23
27
|
//# sourceMappingURL=component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/consent/component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/consent/component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EACgD,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EACrG,MAAM,uBAAuB,CAAA;AAqC9B;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,kBAAkB,CAWrD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,EAAE,CAAC,iBAAiB,CAQnD,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { CookieConsent, CookiePolicy } from '@owlmeans/web-consent';
|
|
2
|
+
import { CookieConsent, CookiePolicy, } from '@owlmeans/web-consent';
|
|
3
3
|
import { useLanguage } from '@owlmeans/client-i18n';
|
|
4
4
|
import { useContext } from '../context.js';
|
|
5
5
|
import { useConsentTranslate } from './translate.js';
|
|
@@ -12,6 +12,12 @@ const BoundCookieConsent = ({ menuPresent, ...props }) => {
|
|
|
12
12
|
return _jsx(CookieConsent, { ...props, locale: locale, translate: translate, noReopenButton: props.noReopenButton ?? menuPresent });
|
|
13
13
|
};
|
|
14
14
|
const MenuAwareCookieConsent = props => _jsx(BoundCookieConsent, { ...props, menuPresent: useConsentWidgetPresent() });
|
|
15
|
+
/**
|
|
16
|
+
* The geo gate in force: the prop, else `cfg.cookieConsent.geo`, else — when the application
|
|
17
|
+
* appended a locator of its own — the gate with nothing but that locator.
|
|
18
|
+
*/
|
|
19
|
+
const geoOf = (prop, context) => prop ?? context.cfg.cookieConsent?.geo ?? (typeof context.consentGeo === 'function' ? {} : undefined);
|
|
20
|
+
void _localeParity;
|
|
15
21
|
/**
|
|
16
22
|
* The consent dialog, bound to this application's language and translations.
|
|
17
23
|
*
|
|
@@ -32,15 +38,23 @@ const MenuAwareCookieConsent = props => _jsx(BoundCookieConsent, { ...props, men
|
|
|
32
38
|
*/
|
|
33
39
|
export const PanelCookieConsent = props => {
|
|
34
40
|
const context = useContext();
|
|
41
|
+
const mode = props.mode ?? context.cfg.cookieConsent?.mode;
|
|
42
|
+
const geo = geoOf(props.geo, context);
|
|
43
|
+
const bound = { ...props, ...(mode != null ? { mode } : {}), ...(geo != null ? { geo } : {}) };
|
|
35
44
|
return typeof context.consentWidget === 'function'
|
|
36
|
-
? _jsx(MenuAwareCookieConsent, { ...
|
|
37
|
-
: _jsx(BoundCookieConsent, { ...
|
|
45
|
+
? _jsx(MenuAwareCookieConsent, { ...bound })
|
|
46
|
+
: _jsx(BoundCookieConsent, { ...bound });
|
|
38
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* The cookie-policy page, bound like the dialog — and told about the geo gate the same way, so it
|
|
50
|
+
* states the regional rule exactly when the dialog applies it.
|
|
51
|
+
*/
|
|
39
52
|
export const PanelCookiePolicy = props => {
|
|
53
|
+
const context = useContext();
|
|
40
54
|
const [lng] = useLanguage();
|
|
41
55
|
const locale = props.locale ?? lng;
|
|
42
56
|
const translate = useConsentTranslate(locale, props.translate);
|
|
43
|
-
|
|
57
|
+
const geo = geoOf(props.geo, context);
|
|
58
|
+
return _jsx(CookiePolicy, { ...props, ...(geo != null ? { geo } : {}), locale: locale, translate: translate });
|
|
44
59
|
};
|
|
45
|
-
void _localeParity;
|
|
46
60
|
//# sourceMappingURL=component.js.map
|