@pixelume/sdk 0.2.0 → 0.3.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/CHANGELOG.md +20 -1
- package/README.md +46 -9
- package/dist/ui/index.d.ts +2 -0
- package/dist/ui/index.js +2 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/styles.d.ts +1 -0
- package/dist/ui/styles.js +402 -0
- package/dist/ui/styles.js.map +1 -0
- package/dist/ui/widget.d.ts +29 -0
- package/dist/ui/widget.js +378 -0
- package/dist/ui/widget.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,24 @@ conter mudanças incompatíveis, sempre listadas em **Changed/Removed**.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-10-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Entry point opt-in `@pixelume/sdk/ui` com `mountPixelumeWidget()`, Shadow DOM aberto e controlador
|
|
15
|
+
`hide()`, `show()` e `destroy()`.
|
|
16
|
+
- Widget oficial responsivo com estados de visitante, carregamento, autenticado e erro; login/logout
|
|
17
|
+
reutilizam exclusivamente `client.auth`.
|
|
18
|
+
- Posição, distância das bordas, container e `z-index` configuráveis, incluindo safe areas mobile.
|
|
19
|
+
- Navegação por teclado, Escape com devolução de foco, foco visível, região de status e isolamento de
|
|
20
|
+
eventos pointer/touch/teclado do jogo.
|
|
21
|
+
- Testes DOM do widget e validação dos dois entrypoints no consumidor empacotado.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- O exemplo Vite agora monta também o widget oficial, mantendo os controles headless para demonstrar os
|
|
26
|
+
dois modos de consumo.
|
|
27
|
+
|
|
10
28
|
## [0.2.0] - 2026-10-13
|
|
11
29
|
|
|
12
30
|
### Added
|
|
@@ -47,7 +65,8 @@ conter mudanças incompatíveis, sempre listadas em **Changed/Removed**.
|
|
|
47
65
|
`invalid_response`) e `isPixelumeError()`.
|
|
48
66
|
- Build ESM + `.d.ts`, CI e workflow de publicação via npm Trusted Publishing.
|
|
49
67
|
|
|
50
|
-
[Unreleased]: https://github.com/ericksonnascimento/pixelume-sdk/compare/v0.
|
|
68
|
+
[Unreleased]: https://github.com/ericksonnascimento/pixelume-sdk/compare/v0.3.0...HEAD
|
|
69
|
+
[0.3.0]: https://github.com/ericksonnascimento/pixelume-sdk/compare/v0.2.0...v0.3.0
|
|
51
70
|
[0.2.0]: https://github.com/ericksonnascimento/pixelume-sdk/compare/v0.1.1...v0.2.0
|
|
52
71
|
[0.1.1]: https://github.com/ericksonnascimento/pixelume-sdk/compare/v0.1.0...v0.1.1
|
|
53
72
|
[0.1.0]: https://github.com/ericksonnascimento/pixelume-sdk/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# @pixelume/sdk
|
|
2
2
|
|
|
3
|
-
SDK TypeScript
|
|
4
|
-
|
|
5
|
-
dependências de runtime,
|
|
3
|
+
SDK TypeScript para jogos web da Pixelume. O core headless continua sendo o padrão; a versão 0.3 adiciona
|
|
4
|
+
um widget oficial opt-in em `@pixelume/sdk/ui`. Os dois modos usam a mesma autenticação centralizada com
|
|
5
|
+
OAuth 2.0 Authorization Code + PKCE S256. Não há dependências de runtime, senha no jogo nem
|
|
6
|
+
`client_secret`.
|
|
6
7
|
|
|
7
8
|
## Instalação
|
|
8
9
|
|
|
@@ -25,7 +26,7 @@ Não são aceitos curingas, prefixos ou callbacks enviados dinamicamente. O clie
|
|
|
25
26
|
`pixelume-local-dev`, exclusivamente com `http://localhost:4173/oauth/callback` e
|
|
26
27
|
`http://127.0.0.1:4173/oauth/callback`. Jogos publicados exigem migration/configuração revisada na API.
|
|
27
28
|
|
|
28
|
-
## Uso
|
|
29
|
+
## Uso headless
|
|
29
30
|
|
|
30
31
|
```ts
|
|
31
32
|
import { Pixelume, isPixelumeError } from '@pixelume/sdk';
|
|
@@ -64,6 +65,41 @@ logoutButton.addEventListener('click', async () => {
|
|
|
64
65
|
unsubscribe();
|
|
65
66
|
```
|
|
66
67
|
|
|
68
|
+
Importar ou instanciar o core não cria elementos, não injeta estilos e não ativa UI. O health check
|
|
69
|
+
também é totalmente independente: chamar `/health` nunca monta o widget.
|
|
70
|
+
|
|
71
|
+
## Widget opcional
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { Pixelume } from '@pixelume/sdk';
|
|
75
|
+
import { mountPixelumeWidget } from '@pixelume/sdk/ui';
|
|
76
|
+
|
|
77
|
+
const pixelume = new Pixelume({
|
|
78
|
+
gameId: 'rail-puzzle',
|
|
79
|
+
redirectUri: 'https://rail-puzzle.pixelume.com.br/oauth/callback',
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await pixelume.initialize();
|
|
83
|
+
|
|
84
|
+
const widget = mountPixelumeWidget(pixelume, {
|
|
85
|
+
position: 'bottom-right',
|
|
86
|
+
offset: 16,
|
|
87
|
+
theme: 'pixel',
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Ao esconder controles, pausar ou trocar de tela:
|
|
91
|
+
widget.hide();
|
|
92
|
+
widget.show();
|
|
93
|
+
|
|
94
|
+
// Ao encerrar a tela/jogo:
|
|
95
|
+
widget.destroy();
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
O painel usa Shadow DOM aberto, não aplica CSS global e chama somente `pixelume.auth.login()` e
|
|
99
|
+
`pixelume.auth.logout()`. Entrar sempre redireciona ao portal Pixelume Auth; o widget não exibe campos de
|
|
100
|
+
e-mail ou senha. Para overlays próprios ou canvas fullscreen, passe `container`, ajuste `position`,
|
|
101
|
+
`offset` e `zIndex`. Veja o [guia completo do widget](docs/phase-03-widget.md).
|
|
102
|
+
|
|
67
103
|
`pixelume.auth.state.status` é `uninitialized`, `redirecting`, `exchanging`, `anonymous` ou
|
|
68
104
|
`authenticated`. O estado anônimo informa `reason` (`visitor`, `cancelled`, `expired`, `logged_out` ou
|
|
69
105
|
`error`) e, em falha, um `PixelumeError`. Cancelar no portal resulta em visitante, não em exceção.
|
|
@@ -146,10 +182,11 @@ local, mas não diretamente de outro domínio no browser.
|
|
|
146
182
|
|
|
147
183
|
## Compatibilidade
|
|
148
184
|
|
|
149
|
-
| SDK | Pixelume API | Pixelume Auth | Recursos
|
|
150
|
-
| ------- | ---------------------------------------------------- | ------------------------------ |
|
|
151
|
-
| `0.
|
|
152
|
-
| `0.
|
|
185
|
+
| SDK | Pixelume API | Pixelume Auth | Recursos |
|
|
186
|
+
| ------- | ---------------------------------------------------- | ------------------------------ | ----------------------------------------------- |
|
|
187
|
+
| `0.3.x` | OpenAPI `0.4.0`, release SSO `3846479` ou compatível | Fase 2 `3a1ded4` ou compatível | Widget opt-in, SSO PKCE, perfil, logout, health |
|
|
188
|
+
| `0.2.x` | OpenAPI `0.4.0`, release SSO `3846479` ou compatível | Fase 2 `3a1ded4` ou compatível | SSO PKCE, perfil, logout, health |
|
|
189
|
+
| `0.1.x` | API anterior/atual para `/health` | não consumido | fundação e health apenas |
|
|
153
190
|
|
|
154
191
|
Como o pacote ainda está em `0.x`, mudanças incompatíveis usam incremento _minor_ e são listadas no
|
|
155
192
|
[CHANGELOG](CHANGELOG.md).
|
|
@@ -164,7 +201,7 @@ npm run verify
|
|
|
164
201
|
npm run example:smoke # leitura opcional da API real
|
|
165
202
|
```
|
|
166
203
|
|
|
167
|
-
Mais detalhes: [integração SSO](docs/SSO_INTEGRATION.md),
|
|
204
|
+
Mais detalhes: [widget oficial](docs/phase-03-widget.md), [integração SSO](docs/SSO_INTEGRATION.md),
|
|
168
205
|
[auditoria do contrato](docs/SSO_CONTRACT_AUDIT.md), [arquitetura](docs/architecture.md) e
|
|
169
206
|
[publicação](docs/publishing.md).
|
|
170
207
|
|
package/dist/ui/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export { mountPixelumeWidget } from './widget.js';\nexport type {\n PixelumeWidgetController,\n PixelumeWidgetOptions,\n PixelumeWidgetPosition,\n} from './widget.js';\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WIDGET_STYLES = "\n:host {\n all: initial;\n position: fixed;\n z-index: var(--pixelume-z-index, 2147483000);\n display: block;\n color-scheme: dark;\n contain: layout style;\n pointer-events: none;\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host([data-contained]) {\n position: absolute;\n}\n\n:host([data-position=\"top-left\"]) {\n inset-block-start: calc(var(--pixelume-offset) + env(safe-area-inset-top, 0px));\n inset-inline-start: calc(var(--pixelume-offset) + env(safe-area-inset-left, 0px));\n}\n\n:host([data-position=\"top-right\"]) {\n inset-block-start: calc(var(--pixelume-offset) + env(safe-area-inset-top, 0px));\n inset-inline-end: calc(var(--pixelume-offset) + env(safe-area-inset-right, 0px));\n}\n\n:host([data-position=\"bottom-left\"]) {\n inset-block-end: calc(var(--pixelume-offset) + env(safe-area-inset-bottom, 0px));\n inset-inline-start: calc(var(--pixelume-offset) + env(safe-area-inset-left, 0px));\n}\n\n:host([data-position=\"bottom-right\"]) {\n inset-block-end: calc(var(--pixelume-offset) + env(safe-area-inset-bottom, 0px));\n inset-inline-end: calc(var(--pixelume-offset) + env(safe-area-inset-right, 0px));\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n}\n\n.root {\n --night: oklch(25% 0.035 263);\n --night-deep: oklch(18% 0.03 263);\n --surface: oklch(30% 0.04 263);\n --surface-raised: oklch(35% 0.045 263);\n --lume: oklch(79% 0.13 67);\n --lume-bright: oklch(88% 0.1 76);\n --lume-deep: oklch(63% 0.13 48);\n --mint: oklch(81% 0.08 171);\n --text: oklch(94% 0.02 78);\n --muted: oklch(80% 0.02 78);\n --danger: oklch(78% 0.12 24);\n --line: oklch(92% 0.02 78 / 0.24);\n --pixel: 3px;\n display: flex;\n gap: 0.75rem;\n align-items: flex-end;\n inline-size: max-content;\n max-inline-size: calc(100vw - 2rem);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n font-size: 1rem;\n line-height: 1.45;\n color: var(--text);\n pointer-events: auto;\n -webkit-font-smoothing: antialiased;\n}\n\n:host([data-position^=\"bottom\"]) .root {\n flex-direction: column-reverse;\n}\n\n:host([data-position^=\"top\"]) .root {\n flex-direction: column;\n}\n\n:host([data-position$=\"left\"]) .root {\n align-items: flex-start;\n}\n\n.trigger,\n.panel,\n.action,\n.close {\n border: 0;\n border-radius: 0;\n}\n\n.trigger,\n.action {\n box-shadow:\n 0 calc(-1 * var(--pixel)) 0 var(--edge),\n 0 var(--pixel) 0 var(--edge-bottom),\n calc(-1 * var(--pixel)) 0 var(--edge),\n var(--pixel) 0 var(--edge);\n}\n\n.trigger {\n --edge: var(--lume);\n --edge-bottom: var(--lume-deep);\n display: inline-flex;\n align-items: center;\n gap: 0.625rem;\n min-block-size: 2.75rem;\n margin: var(--pixel);\n padding: 0.625rem 0.875rem;\n color: var(--night-deep);\n background: var(--lume);\n font-weight: 750;\n cursor: pointer;\n touch-action: manipulation;\n transition:\n transform 160ms cubic-bezier(0.16, 1, 0.3, 1),\n background-color 160ms linear;\n}\n\n.trigger:hover {\n background: var(--lume-bright);\n}\n\n.trigger:active {\n transform: translateY(2px);\n}\n\n.trigger:focus-visible,\n.action:focus-visible,\n.close:focus-visible {\n outline: 3px solid var(--mint);\n outline-offset: 4px;\n}\n\n.mark {\n position: relative;\n flex: none;\n inline-size: 1rem;\n block-size: 1rem;\n color: currentColor;\n}\n\n.mark::before,\n.mark::after {\n content: \"\";\n position: absolute;\n background: currentColor;\n}\n\n.mark::before {\n inset: 0.25rem;\n}\n\n.mark::after {\n inset: 0;\n clip-path: polygon(37.5% 0, 62.5% 0, 62.5% 37.5%, 100% 37.5%, 100% 62.5%, 62.5% 62.5%, 62.5% 100%, 37.5% 100%, 37.5% 62.5%, 0 62.5%, 0 37.5%, 37.5% 37.5%);\n opacity: 0.72;\n}\n\n.presence {\n inline-size: 0.5rem;\n block-size: 0.5rem;\n background: var(--night-deep);\n opacity: 0.5;\n}\n\n.trigger[data-authenticated] .presence {\n background: oklch(48% 0.12 168);\n opacity: 1;\n}\n\n.panel {\n inline-size: min(21.5rem, calc(100vw - 2rem));\n margin: var(--pixel);\n color: var(--text);\n background: var(--night);\n box-shadow:\n 0 calc(-1 * var(--pixel)) 0 var(--line),\n 0 var(--pixel) 0 var(--surface-raised),\n calc(-1 * var(--pixel)) 0 var(--line),\n var(--pixel) 0 var(--line),\n 0 1rem 2.5rem oklch(8% 0.03 263 / 0.42);\n overflow: hidden;\n}\n\n.panel[hidden] {\n display: none;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n min-block-size: 3rem;\n padding: 0.625rem 0.75rem 0.625rem 1rem;\n border-block-end: 1px solid var(--line);\n}\n\n.brand {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n color: var(--lume-bright);\n font-family: ui-monospace, \"SFMono-Regular\", Consolas, monospace;\n font-size: 0.8125rem;\n font-weight: 750;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.brand .mark {\n inline-size: 0.75rem;\n block-size: 0.75rem;\n}\n\n.close {\n display: grid;\n place-items: center;\n inline-size: 2.5rem;\n block-size: 2.5rem;\n padding: 0;\n color: var(--muted);\n background: transparent;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n touch-action: manipulation;\n}\n\n.close:hover {\n color: var(--text);\n background: var(--surface);\n}\n\n.content {\n display: grid;\n gap: 1rem;\n padding: 1.25rem;\n}\n\n.identity {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n align-items: center;\n gap: 0.875rem;\n}\n\n.avatar {\n display: grid;\n place-items: center;\n inline-size: 2.75rem;\n block-size: 2.75rem;\n color: var(--night-deep);\n background: var(--mint);\n box-shadow:\n 0 -3px 0 var(--mint),\n 0 3px 0 oklch(62% 0.08 171),\n -3px 0 0 var(--mint),\n 3px 0 0 var(--mint);\n font-family: ui-monospace, \"SFMono-Regular\", Consolas, monospace;\n font-weight: 800;\n}\n\n.title,\n.message {\n margin: 0;\n}\n\n.title {\n color: var(--text);\n font-size: 1.125rem;\n font-weight: 760;\n line-height: 1.25;\n overflow-wrap: anywhere;\n}\n\n.message {\n max-inline-size: 34ch;\n color: var(--muted);\n font-size: 0.875rem;\n}\n\n.state-copy {\n display: grid;\n gap: 0.375rem;\n}\n\n.notice {\n margin: 0;\n padding: 0.75rem;\n color: var(--danger);\n background: oklch(25% 0.055 24);\n border: 1px solid oklch(78% 0.12 24 / 0.35);\n font-size: 0.8125rem;\n}\n\n.action {\n --edge: var(--lume);\n --edge-bottom: var(--lume-deep);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-block-size: 2.75rem;\n inline-size: calc(100% - 2 * var(--pixel));\n margin: var(--pixel);\n padding: 0.6875rem 1rem;\n color: var(--night-deep);\n background: var(--lume);\n font-weight: 750;\n cursor: pointer;\n touch-action: manipulation;\n transition:\n transform 160ms cubic-bezier(0.16, 1, 0.3, 1),\n background-color 160ms linear;\n}\n\n.action:hover:not(:disabled) {\n background: var(--lume-bright);\n}\n\n.action:active:not(:disabled) {\n transform: translateY(2px);\n}\n\n.action.secondary {\n --edge: var(--line);\n --edge-bottom: var(--surface-raised);\n color: var(--text);\n background: var(--surface);\n}\n\n.action.secondary:hover:not(:disabled) {\n --edge: var(--mint);\n color: var(--mint);\n background: var(--surface-raised);\n}\n\n.action:disabled {\n cursor: wait;\n opacity: 0.68;\n}\n\n.loading {\n display: grid;\n gap: 0.625rem;\n padding-block: 0.25rem;\n}\n\n.loading-line {\n block-size: 0.75rem;\n background: var(--surface-raised);\n animation: pixel-pulse 1.2s steps(4, end) infinite;\n}\n\n.loading-line:first-child {\n inline-size: 62%;\n}\n\n.loading-line:last-child {\n inline-size: 88%;\n}\n\n.sr-only {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n@keyframes pixel-pulse {\n 0%, 100% { opacity: 0.45; }\n 50% { opacity: 1; }\n}\n\n@media (max-width: 30rem) {\n .trigger {\n padding-inline: 0.75rem;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n";
|
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
export const WIDGET_STYLES = `
|
|
2
|
+
:host {
|
|
3
|
+
all: initial;
|
|
4
|
+
position: fixed;
|
|
5
|
+
z-index: var(--pixelume-z-index, 2147483000);
|
|
6
|
+
display: block;
|
|
7
|
+
color-scheme: dark;
|
|
8
|
+
contain: layout style;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:host([hidden]) {
|
|
13
|
+
display: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
:host([data-contained]) {
|
|
17
|
+
position: absolute;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:host([data-position="top-left"]) {
|
|
21
|
+
inset-block-start: calc(var(--pixelume-offset) + env(safe-area-inset-top, 0px));
|
|
22
|
+
inset-inline-start: calc(var(--pixelume-offset) + env(safe-area-inset-left, 0px));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
:host([data-position="top-right"]) {
|
|
26
|
+
inset-block-start: calc(var(--pixelume-offset) + env(safe-area-inset-top, 0px));
|
|
27
|
+
inset-inline-end: calc(var(--pixelume-offset) + env(safe-area-inset-right, 0px));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:host([data-position="bottom-left"]) {
|
|
31
|
+
inset-block-end: calc(var(--pixelume-offset) + env(safe-area-inset-bottom, 0px));
|
|
32
|
+
inset-inline-start: calc(var(--pixelume-offset) + env(safe-area-inset-left, 0px));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:host([data-position="bottom-right"]) {
|
|
36
|
+
inset-block-end: calc(var(--pixelume-offset) + env(safe-area-inset-bottom, 0px));
|
|
37
|
+
inset-inline-end: calc(var(--pixelume-offset) + env(safe-area-inset-right, 0px));
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
*,
|
|
41
|
+
*::before,
|
|
42
|
+
*::after {
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
button {
|
|
47
|
+
font: inherit;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.root {
|
|
51
|
+
--night: oklch(25% 0.035 263);
|
|
52
|
+
--night-deep: oklch(18% 0.03 263);
|
|
53
|
+
--surface: oklch(30% 0.04 263);
|
|
54
|
+
--surface-raised: oklch(35% 0.045 263);
|
|
55
|
+
--lume: oklch(79% 0.13 67);
|
|
56
|
+
--lume-bright: oklch(88% 0.1 76);
|
|
57
|
+
--lume-deep: oklch(63% 0.13 48);
|
|
58
|
+
--mint: oklch(81% 0.08 171);
|
|
59
|
+
--text: oklch(94% 0.02 78);
|
|
60
|
+
--muted: oklch(80% 0.02 78);
|
|
61
|
+
--danger: oklch(78% 0.12 24);
|
|
62
|
+
--line: oklch(92% 0.02 78 / 0.24);
|
|
63
|
+
--pixel: 3px;
|
|
64
|
+
display: flex;
|
|
65
|
+
gap: 0.75rem;
|
|
66
|
+
align-items: flex-end;
|
|
67
|
+
inline-size: max-content;
|
|
68
|
+
max-inline-size: calc(100vw - 2rem);
|
|
69
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
|
|
70
|
+
font-size: 1rem;
|
|
71
|
+
line-height: 1.45;
|
|
72
|
+
color: var(--text);
|
|
73
|
+
pointer-events: auto;
|
|
74
|
+
-webkit-font-smoothing: antialiased;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
:host([data-position^="bottom"]) .root {
|
|
78
|
+
flex-direction: column-reverse;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:host([data-position^="top"]) .root {
|
|
82
|
+
flex-direction: column;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:host([data-position$="left"]) .root {
|
|
86
|
+
align-items: flex-start;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.trigger,
|
|
90
|
+
.panel,
|
|
91
|
+
.action,
|
|
92
|
+
.close {
|
|
93
|
+
border: 0;
|
|
94
|
+
border-radius: 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.trigger,
|
|
98
|
+
.action {
|
|
99
|
+
box-shadow:
|
|
100
|
+
0 calc(-1 * var(--pixel)) 0 var(--edge),
|
|
101
|
+
0 var(--pixel) 0 var(--edge-bottom),
|
|
102
|
+
calc(-1 * var(--pixel)) 0 var(--edge),
|
|
103
|
+
var(--pixel) 0 var(--edge);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.trigger {
|
|
107
|
+
--edge: var(--lume);
|
|
108
|
+
--edge-bottom: var(--lume-deep);
|
|
109
|
+
display: inline-flex;
|
|
110
|
+
align-items: center;
|
|
111
|
+
gap: 0.625rem;
|
|
112
|
+
min-block-size: 2.75rem;
|
|
113
|
+
margin: var(--pixel);
|
|
114
|
+
padding: 0.625rem 0.875rem;
|
|
115
|
+
color: var(--night-deep);
|
|
116
|
+
background: var(--lume);
|
|
117
|
+
font-weight: 750;
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
touch-action: manipulation;
|
|
120
|
+
transition:
|
|
121
|
+
transform 160ms cubic-bezier(0.16, 1, 0.3, 1),
|
|
122
|
+
background-color 160ms linear;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.trigger:hover {
|
|
126
|
+
background: var(--lume-bright);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.trigger:active {
|
|
130
|
+
transform: translateY(2px);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.trigger:focus-visible,
|
|
134
|
+
.action:focus-visible,
|
|
135
|
+
.close:focus-visible {
|
|
136
|
+
outline: 3px solid var(--mint);
|
|
137
|
+
outline-offset: 4px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.mark {
|
|
141
|
+
position: relative;
|
|
142
|
+
flex: none;
|
|
143
|
+
inline-size: 1rem;
|
|
144
|
+
block-size: 1rem;
|
|
145
|
+
color: currentColor;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.mark::before,
|
|
149
|
+
.mark::after {
|
|
150
|
+
content: "";
|
|
151
|
+
position: absolute;
|
|
152
|
+
background: currentColor;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.mark::before {
|
|
156
|
+
inset: 0.25rem;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.mark::after {
|
|
160
|
+
inset: 0;
|
|
161
|
+
clip-path: polygon(37.5% 0, 62.5% 0, 62.5% 37.5%, 100% 37.5%, 100% 62.5%, 62.5% 62.5%, 62.5% 100%, 37.5% 100%, 37.5% 62.5%, 0 62.5%, 0 37.5%, 37.5% 37.5%);
|
|
162
|
+
opacity: 0.72;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.presence {
|
|
166
|
+
inline-size: 0.5rem;
|
|
167
|
+
block-size: 0.5rem;
|
|
168
|
+
background: var(--night-deep);
|
|
169
|
+
opacity: 0.5;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.trigger[data-authenticated] .presence {
|
|
173
|
+
background: oklch(48% 0.12 168);
|
|
174
|
+
opacity: 1;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.panel {
|
|
178
|
+
inline-size: min(21.5rem, calc(100vw - 2rem));
|
|
179
|
+
margin: var(--pixel);
|
|
180
|
+
color: var(--text);
|
|
181
|
+
background: var(--night);
|
|
182
|
+
box-shadow:
|
|
183
|
+
0 calc(-1 * var(--pixel)) 0 var(--line),
|
|
184
|
+
0 var(--pixel) 0 var(--surface-raised),
|
|
185
|
+
calc(-1 * var(--pixel)) 0 var(--line),
|
|
186
|
+
var(--pixel) 0 var(--line),
|
|
187
|
+
0 1rem 2.5rem oklch(8% 0.03 263 / 0.42);
|
|
188
|
+
overflow: hidden;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.panel[hidden] {
|
|
192
|
+
display: none;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.panel-header {
|
|
196
|
+
display: flex;
|
|
197
|
+
align-items: center;
|
|
198
|
+
justify-content: space-between;
|
|
199
|
+
gap: 1rem;
|
|
200
|
+
min-block-size: 3rem;
|
|
201
|
+
padding: 0.625rem 0.75rem 0.625rem 1rem;
|
|
202
|
+
border-block-end: 1px solid var(--line);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.brand {
|
|
206
|
+
display: inline-flex;
|
|
207
|
+
align-items: center;
|
|
208
|
+
gap: 0.5rem;
|
|
209
|
+
color: var(--lume-bright);
|
|
210
|
+
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
|
211
|
+
font-size: 0.8125rem;
|
|
212
|
+
font-weight: 750;
|
|
213
|
+
letter-spacing: 0.08em;
|
|
214
|
+
text-transform: uppercase;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.brand .mark {
|
|
218
|
+
inline-size: 0.75rem;
|
|
219
|
+
block-size: 0.75rem;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.close {
|
|
223
|
+
display: grid;
|
|
224
|
+
place-items: center;
|
|
225
|
+
inline-size: 2.5rem;
|
|
226
|
+
block-size: 2.5rem;
|
|
227
|
+
padding: 0;
|
|
228
|
+
color: var(--muted);
|
|
229
|
+
background: transparent;
|
|
230
|
+
font-size: 1.5rem;
|
|
231
|
+
line-height: 1;
|
|
232
|
+
cursor: pointer;
|
|
233
|
+
touch-action: manipulation;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.close:hover {
|
|
237
|
+
color: var(--text);
|
|
238
|
+
background: var(--surface);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.content {
|
|
242
|
+
display: grid;
|
|
243
|
+
gap: 1rem;
|
|
244
|
+
padding: 1.25rem;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.identity {
|
|
248
|
+
display: grid;
|
|
249
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
250
|
+
align-items: center;
|
|
251
|
+
gap: 0.875rem;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.avatar {
|
|
255
|
+
display: grid;
|
|
256
|
+
place-items: center;
|
|
257
|
+
inline-size: 2.75rem;
|
|
258
|
+
block-size: 2.75rem;
|
|
259
|
+
color: var(--night-deep);
|
|
260
|
+
background: var(--mint);
|
|
261
|
+
box-shadow:
|
|
262
|
+
0 -3px 0 var(--mint),
|
|
263
|
+
0 3px 0 oklch(62% 0.08 171),
|
|
264
|
+
-3px 0 0 var(--mint),
|
|
265
|
+
3px 0 0 var(--mint);
|
|
266
|
+
font-family: ui-monospace, "SFMono-Regular", Consolas, monospace;
|
|
267
|
+
font-weight: 800;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.title,
|
|
271
|
+
.message {
|
|
272
|
+
margin: 0;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.title {
|
|
276
|
+
color: var(--text);
|
|
277
|
+
font-size: 1.125rem;
|
|
278
|
+
font-weight: 760;
|
|
279
|
+
line-height: 1.25;
|
|
280
|
+
overflow-wrap: anywhere;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.message {
|
|
284
|
+
max-inline-size: 34ch;
|
|
285
|
+
color: var(--muted);
|
|
286
|
+
font-size: 0.875rem;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.state-copy {
|
|
290
|
+
display: grid;
|
|
291
|
+
gap: 0.375rem;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.notice {
|
|
295
|
+
margin: 0;
|
|
296
|
+
padding: 0.75rem;
|
|
297
|
+
color: var(--danger);
|
|
298
|
+
background: oklch(25% 0.055 24);
|
|
299
|
+
border: 1px solid oklch(78% 0.12 24 / 0.35);
|
|
300
|
+
font-size: 0.8125rem;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.action {
|
|
304
|
+
--edge: var(--lume);
|
|
305
|
+
--edge-bottom: var(--lume-deep);
|
|
306
|
+
display: inline-flex;
|
|
307
|
+
align-items: center;
|
|
308
|
+
justify-content: center;
|
|
309
|
+
min-block-size: 2.75rem;
|
|
310
|
+
inline-size: calc(100% - 2 * var(--pixel));
|
|
311
|
+
margin: var(--pixel);
|
|
312
|
+
padding: 0.6875rem 1rem;
|
|
313
|
+
color: var(--night-deep);
|
|
314
|
+
background: var(--lume);
|
|
315
|
+
font-weight: 750;
|
|
316
|
+
cursor: pointer;
|
|
317
|
+
touch-action: manipulation;
|
|
318
|
+
transition:
|
|
319
|
+
transform 160ms cubic-bezier(0.16, 1, 0.3, 1),
|
|
320
|
+
background-color 160ms linear;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.action:hover:not(:disabled) {
|
|
324
|
+
background: var(--lume-bright);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.action:active:not(:disabled) {
|
|
328
|
+
transform: translateY(2px);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.action.secondary {
|
|
332
|
+
--edge: var(--line);
|
|
333
|
+
--edge-bottom: var(--surface-raised);
|
|
334
|
+
color: var(--text);
|
|
335
|
+
background: var(--surface);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.action.secondary:hover:not(:disabled) {
|
|
339
|
+
--edge: var(--mint);
|
|
340
|
+
color: var(--mint);
|
|
341
|
+
background: var(--surface-raised);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.action:disabled {
|
|
345
|
+
cursor: wait;
|
|
346
|
+
opacity: 0.68;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.loading {
|
|
350
|
+
display: grid;
|
|
351
|
+
gap: 0.625rem;
|
|
352
|
+
padding-block: 0.25rem;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.loading-line {
|
|
356
|
+
block-size: 0.75rem;
|
|
357
|
+
background: var(--surface-raised);
|
|
358
|
+
animation: pixel-pulse 1.2s steps(4, end) infinite;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.loading-line:first-child {
|
|
362
|
+
inline-size: 62%;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.loading-line:last-child {
|
|
366
|
+
inline-size: 88%;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.sr-only {
|
|
370
|
+
position: absolute;
|
|
371
|
+
inline-size: 1px;
|
|
372
|
+
block-size: 1px;
|
|
373
|
+
padding: 0;
|
|
374
|
+
margin: -1px;
|
|
375
|
+
overflow: hidden;
|
|
376
|
+
clip: rect(0, 0, 0, 0);
|
|
377
|
+
white-space: nowrap;
|
|
378
|
+
border: 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
@keyframes pixel-pulse {
|
|
382
|
+
0%, 100% { opacity: 0.45; }
|
|
383
|
+
50% { opacity: 1; }
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
@media (max-width: 30rem) {
|
|
387
|
+
.trigger {
|
|
388
|
+
padding-inline: 0.75rem;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
@media (prefers-reduced-motion: reduce) {
|
|
393
|
+
*,
|
|
394
|
+
*::before,
|
|
395
|
+
*::after {
|
|
396
|
+
animation-duration: 0.01ms !important;
|
|
397
|
+
animation-iteration-count: 1 !important;
|
|
398
|
+
transition-duration: 0.01ms !important;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
`;
|
|
402
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/ui/styles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgZ5B,CAAC","sourcesContent":["export const WIDGET_STYLES = `\n:host {\n all: initial;\n position: fixed;\n z-index: var(--pixelume-z-index, 2147483000);\n display: block;\n color-scheme: dark;\n contain: layout style;\n pointer-events: none;\n}\n\n:host([hidden]) {\n display: none;\n}\n\n:host([data-contained]) {\n position: absolute;\n}\n\n:host([data-position=\"top-left\"]) {\n inset-block-start: calc(var(--pixelume-offset) + env(safe-area-inset-top, 0px));\n inset-inline-start: calc(var(--pixelume-offset) + env(safe-area-inset-left, 0px));\n}\n\n:host([data-position=\"top-right\"]) {\n inset-block-start: calc(var(--pixelume-offset) + env(safe-area-inset-top, 0px));\n inset-inline-end: calc(var(--pixelume-offset) + env(safe-area-inset-right, 0px));\n}\n\n:host([data-position=\"bottom-left\"]) {\n inset-block-end: calc(var(--pixelume-offset) + env(safe-area-inset-bottom, 0px));\n inset-inline-start: calc(var(--pixelume-offset) + env(safe-area-inset-left, 0px));\n}\n\n:host([data-position=\"bottom-right\"]) {\n inset-block-end: calc(var(--pixelume-offset) + env(safe-area-inset-bottom, 0px));\n inset-inline-end: calc(var(--pixelume-offset) + env(safe-area-inset-right, 0px));\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nbutton {\n font: inherit;\n}\n\n.root {\n --night: oklch(25% 0.035 263);\n --night-deep: oklch(18% 0.03 263);\n --surface: oklch(30% 0.04 263);\n --surface-raised: oklch(35% 0.045 263);\n --lume: oklch(79% 0.13 67);\n --lume-bright: oklch(88% 0.1 76);\n --lume-deep: oklch(63% 0.13 48);\n --mint: oklch(81% 0.08 171);\n --text: oklch(94% 0.02 78);\n --muted: oklch(80% 0.02 78);\n --danger: oklch(78% 0.12 24);\n --line: oklch(92% 0.02 78 / 0.24);\n --pixel: 3px;\n display: flex;\n gap: 0.75rem;\n align-items: flex-end;\n inline-size: max-content;\n max-inline-size: calc(100vw - 2rem);\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", system-ui, sans-serif;\n font-size: 1rem;\n line-height: 1.45;\n color: var(--text);\n pointer-events: auto;\n -webkit-font-smoothing: antialiased;\n}\n\n:host([data-position^=\"bottom\"]) .root {\n flex-direction: column-reverse;\n}\n\n:host([data-position^=\"top\"]) .root {\n flex-direction: column;\n}\n\n:host([data-position$=\"left\"]) .root {\n align-items: flex-start;\n}\n\n.trigger,\n.panel,\n.action,\n.close {\n border: 0;\n border-radius: 0;\n}\n\n.trigger,\n.action {\n box-shadow:\n 0 calc(-1 * var(--pixel)) 0 var(--edge),\n 0 var(--pixel) 0 var(--edge-bottom),\n calc(-1 * var(--pixel)) 0 var(--edge),\n var(--pixel) 0 var(--edge);\n}\n\n.trigger {\n --edge: var(--lume);\n --edge-bottom: var(--lume-deep);\n display: inline-flex;\n align-items: center;\n gap: 0.625rem;\n min-block-size: 2.75rem;\n margin: var(--pixel);\n padding: 0.625rem 0.875rem;\n color: var(--night-deep);\n background: var(--lume);\n font-weight: 750;\n cursor: pointer;\n touch-action: manipulation;\n transition:\n transform 160ms cubic-bezier(0.16, 1, 0.3, 1),\n background-color 160ms linear;\n}\n\n.trigger:hover {\n background: var(--lume-bright);\n}\n\n.trigger:active {\n transform: translateY(2px);\n}\n\n.trigger:focus-visible,\n.action:focus-visible,\n.close:focus-visible {\n outline: 3px solid var(--mint);\n outline-offset: 4px;\n}\n\n.mark {\n position: relative;\n flex: none;\n inline-size: 1rem;\n block-size: 1rem;\n color: currentColor;\n}\n\n.mark::before,\n.mark::after {\n content: \"\";\n position: absolute;\n background: currentColor;\n}\n\n.mark::before {\n inset: 0.25rem;\n}\n\n.mark::after {\n inset: 0;\n clip-path: polygon(37.5% 0, 62.5% 0, 62.5% 37.5%, 100% 37.5%, 100% 62.5%, 62.5% 62.5%, 62.5% 100%, 37.5% 100%, 37.5% 62.5%, 0 62.5%, 0 37.5%, 37.5% 37.5%);\n opacity: 0.72;\n}\n\n.presence {\n inline-size: 0.5rem;\n block-size: 0.5rem;\n background: var(--night-deep);\n opacity: 0.5;\n}\n\n.trigger[data-authenticated] .presence {\n background: oklch(48% 0.12 168);\n opacity: 1;\n}\n\n.panel {\n inline-size: min(21.5rem, calc(100vw - 2rem));\n margin: var(--pixel);\n color: var(--text);\n background: var(--night);\n box-shadow:\n 0 calc(-1 * var(--pixel)) 0 var(--line),\n 0 var(--pixel) 0 var(--surface-raised),\n calc(-1 * var(--pixel)) 0 var(--line),\n var(--pixel) 0 var(--line),\n 0 1rem 2.5rem oklch(8% 0.03 263 / 0.42);\n overflow: hidden;\n}\n\n.panel[hidden] {\n display: none;\n}\n\n.panel-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n min-block-size: 3rem;\n padding: 0.625rem 0.75rem 0.625rem 1rem;\n border-block-end: 1px solid var(--line);\n}\n\n.brand {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n color: var(--lume-bright);\n font-family: ui-monospace, \"SFMono-Regular\", Consolas, monospace;\n font-size: 0.8125rem;\n font-weight: 750;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n\n.brand .mark {\n inline-size: 0.75rem;\n block-size: 0.75rem;\n}\n\n.close {\n display: grid;\n place-items: center;\n inline-size: 2.5rem;\n block-size: 2.5rem;\n padding: 0;\n color: var(--muted);\n background: transparent;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n touch-action: manipulation;\n}\n\n.close:hover {\n color: var(--text);\n background: var(--surface);\n}\n\n.content {\n display: grid;\n gap: 1rem;\n padding: 1.25rem;\n}\n\n.identity {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n align-items: center;\n gap: 0.875rem;\n}\n\n.avatar {\n display: grid;\n place-items: center;\n inline-size: 2.75rem;\n block-size: 2.75rem;\n color: var(--night-deep);\n background: var(--mint);\n box-shadow:\n 0 -3px 0 var(--mint),\n 0 3px 0 oklch(62% 0.08 171),\n -3px 0 0 var(--mint),\n 3px 0 0 var(--mint);\n font-family: ui-monospace, \"SFMono-Regular\", Consolas, monospace;\n font-weight: 800;\n}\n\n.title,\n.message {\n margin: 0;\n}\n\n.title {\n color: var(--text);\n font-size: 1.125rem;\n font-weight: 760;\n line-height: 1.25;\n overflow-wrap: anywhere;\n}\n\n.message {\n max-inline-size: 34ch;\n color: var(--muted);\n font-size: 0.875rem;\n}\n\n.state-copy {\n display: grid;\n gap: 0.375rem;\n}\n\n.notice {\n margin: 0;\n padding: 0.75rem;\n color: var(--danger);\n background: oklch(25% 0.055 24);\n border: 1px solid oklch(78% 0.12 24 / 0.35);\n font-size: 0.8125rem;\n}\n\n.action {\n --edge: var(--lume);\n --edge-bottom: var(--lume-deep);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-block-size: 2.75rem;\n inline-size: calc(100% - 2 * var(--pixel));\n margin: var(--pixel);\n padding: 0.6875rem 1rem;\n color: var(--night-deep);\n background: var(--lume);\n font-weight: 750;\n cursor: pointer;\n touch-action: manipulation;\n transition:\n transform 160ms cubic-bezier(0.16, 1, 0.3, 1),\n background-color 160ms linear;\n}\n\n.action:hover:not(:disabled) {\n background: var(--lume-bright);\n}\n\n.action:active:not(:disabled) {\n transform: translateY(2px);\n}\n\n.action.secondary {\n --edge: var(--line);\n --edge-bottom: var(--surface-raised);\n color: var(--text);\n background: var(--surface);\n}\n\n.action.secondary:hover:not(:disabled) {\n --edge: var(--mint);\n color: var(--mint);\n background: var(--surface-raised);\n}\n\n.action:disabled {\n cursor: wait;\n opacity: 0.68;\n}\n\n.loading {\n display: grid;\n gap: 0.625rem;\n padding-block: 0.25rem;\n}\n\n.loading-line {\n block-size: 0.75rem;\n background: var(--surface-raised);\n animation: pixel-pulse 1.2s steps(4, end) infinite;\n}\n\n.loading-line:first-child {\n inline-size: 62%;\n}\n\n.loading-line:last-child {\n inline-size: 88%;\n}\n\n.sr-only {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n@keyframes pixel-pulse {\n 0%, 100% { opacity: 0.45; }\n 50% { opacity: 1; }\n}\n\n@media (max-width: 30rem) {\n .trigger {\n padding-inline: 0.75rem;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n}\n`;\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PixelumeClient } from '../core/PixelumeClient.js';
|
|
2
|
+
export type PixelumeWidgetPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
3
|
+
export interface PixelumeWidgetOptions {
|
|
4
|
+
/** Corner used by the widget. Defaults to `bottom-right`. */
|
|
5
|
+
readonly position?: PixelumeWidgetPosition;
|
|
6
|
+
/** Distance from the selected edges in CSS pixels. Defaults to `16`. */
|
|
7
|
+
readonly offset?: number;
|
|
8
|
+
/** Mount target. Defaults to `document.body`; custom targets should establish a containing block. */
|
|
9
|
+
readonly container?: HTMLElement;
|
|
10
|
+
/** Visual treatment. `pixel` is currently the only supported theme. */
|
|
11
|
+
readonly theme?: 'pixel';
|
|
12
|
+
/** Stacking order for the host. Defaults to `2147483000`. */
|
|
13
|
+
readonly zIndex?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface PixelumeWidgetController {
|
|
16
|
+
/** The Shadow DOM host created by the widget. */
|
|
17
|
+
readonly element: HTMLElement;
|
|
18
|
+
/** Hides the widget and closes its panel without changing authentication state. */
|
|
19
|
+
hide(): void;
|
|
20
|
+
/** Shows a previously hidden widget. */
|
|
21
|
+
show(): void;
|
|
22
|
+
/** Removes DOM/listeners/subscriptions. Safe to call more than once. */
|
|
23
|
+
destroy(): void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Mounts the optional Pixelume account widget. Importing this module alone has no DOM side effects.
|
|
27
|
+
* Repeating the call with the same client and container returns the existing controller.
|
|
28
|
+
*/
|
|
29
|
+
export declare function mountPixelumeWidget(pixelume: PixelumeClient, options?: PixelumeWidgetOptions): PixelumeWidgetController;
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { WIDGET_STYLES } from './styles.js';
|
|
2
|
+
const DEFAULT_POSITION = 'bottom-right';
|
|
3
|
+
const DEFAULT_OFFSET = 16;
|
|
4
|
+
const DEFAULT_Z_INDEX = 2_147_483_000;
|
|
5
|
+
const POSITIONS = [
|
|
6
|
+
'top-left',
|
|
7
|
+
'top-right',
|
|
8
|
+
'bottom-left',
|
|
9
|
+
'bottom-right',
|
|
10
|
+
];
|
|
11
|
+
const widgetsByClient = new WeakMap();
|
|
12
|
+
const widgetsByContainer = new WeakMap();
|
|
13
|
+
let nextWidgetId = 1;
|
|
14
|
+
/**
|
|
15
|
+
* Mounts the optional Pixelume account widget. Importing this module alone has no DOM side effects.
|
|
16
|
+
* Repeating the call with the same client and container returns the existing controller.
|
|
17
|
+
*/
|
|
18
|
+
export function mountPixelumeWidget(pixelume, options = {}) {
|
|
19
|
+
assertClient(pixelume);
|
|
20
|
+
const document = resolveDocument(options.container);
|
|
21
|
+
const container = options.container ?? document.body;
|
|
22
|
+
const mounted = widgetsByClient.get(pixelume);
|
|
23
|
+
if (mounted) {
|
|
24
|
+
if (mounted.container === container)
|
|
25
|
+
return mounted.controller;
|
|
26
|
+
throw new Error('This Pixelume client already has a widget mounted in another container');
|
|
27
|
+
}
|
|
28
|
+
const containerOwner = widgetsByContainer.get(container);
|
|
29
|
+
if (containerOwner) {
|
|
30
|
+
throw new Error('This container already has a Pixelume widget mounted');
|
|
31
|
+
}
|
|
32
|
+
const position = resolvePosition(options.position);
|
|
33
|
+
const offset = resolveNumber('offset', options.offset, DEFAULT_OFFSET, 0, 256);
|
|
34
|
+
const zIndex = resolveNumber('zIndex', options.zIndex, DEFAULT_Z_INDEX, 0, 2_147_483_647);
|
|
35
|
+
const theme = options.theme;
|
|
36
|
+
if (theme !== undefined && theme !== 'pixel') {
|
|
37
|
+
throw new Error('Pixelume widget theme must be "pixel"');
|
|
38
|
+
}
|
|
39
|
+
const host = document.createElement('div');
|
|
40
|
+
host.dataset.pixelumeWidget = '';
|
|
41
|
+
host.dataset.position = position;
|
|
42
|
+
host.style.setProperty('--pixelume-offset', `${offset}px`);
|
|
43
|
+
host.style.setProperty('--pixelume-z-index', String(zIndex));
|
|
44
|
+
if (options.container)
|
|
45
|
+
host.dataset.contained = '';
|
|
46
|
+
const shadow = host.attachShadow({ mode: 'open' });
|
|
47
|
+
const style = document.createElement('style');
|
|
48
|
+
style.textContent = WIDGET_STYLES;
|
|
49
|
+
const root = document.createElement('div');
|
|
50
|
+
root.className = 'root';
|
|
51
|
+
const panelId = `pixelume-widget-panel-${nextWidgetId++}`;
|
|
52
|
+
const trigger = button(document, 'trigger', 'Abrir conta Pixelume');
|
|
53
|
+
trigger.type = 'button';
|
|
54
|
+
trigger.setAttribute('aria-expanded', 'false');
|
|
55
|
+
trigger.setAttribute('aria-controls', panelId);
|
|
56
|
+
const triggerMark = document.createElement('span');
|
|
57
|
+
triggerMark.className = 'mark';
|
|
58
|
+
triggerMark.setAttribute('aria-hidden', 'true');
|
|
59
|
+
const triggerLabel = document.createElement('span');
|
|
60
|
+
triggerLabel.className = 'trigger-label';
|
|
61
|
+
triggerLabel.textContent = 'Pixelume';
|
|
62
|
+
const presence = document.createElement('span');
|
|
63
|
+
presence.className = 'presence';
|
|
64
|
+
presence.setAttribute('aria-hidden', 'true');
|
|
65
|
+
trigger.append(triggerMark, triggerLabel, presence);
|
|
66
|
+
const panel = document.createElement('section');
|
|
67
|
+
panel.className = 'panel';
|
|
68
|
+
panel.id = panelId;
|
|
69
|
+
panel.hidden = true;
|
|
70
|
+
panel.setAttribute('aria-label', 'Conta Pixelume');
|
|
71
|
+
panel.setAttribute('aria-live', 'polite');
|
|
72
|
+
const header = document.createElement('div');
|
|
73
|
+
header.className = 'panel-header';
|
|
74
|
+
const brand = document.createElement('span');
|
|
75
|
+
brand.className = 'brand';
|
|
76
|
+
const brandMark = document.createElement('span');
|
|
77
|
+
brandMark.className = 'mark';
|
|
78
|
+
brandMark.setAttribute('aria-hidden', 'true');
|
|
79
|
+
const brandText = document.createElement('span');
|
|
80
|
+
brandText.textContent = 'Pixelume';
|
|
81
|
+
brand.append(brandMark, brandText);
|
|
82
|
+
const close = button(document, 'close', 'Fechar painel da conta');
|
|
83
|
+
close.type = 'button';
|
|
84
|
+
close.textContent = '×';
|
|
85
|
+
close.setAttribute('aria-hidden', 'false');
|
|
86
|
+
header.append(brand, close);
|
|
87
|
+
const content = document.createElement('div');
|
|
88
|
+
content.className = 'content';
|
|
89
|
+
panel.append(header, content);
|
|
90
|
+
root.append(trigger, panel);
|
|
91
|
+
shadow.append(style, root);
|
|
92
|
+
let destroyed = false;
|
|
93
|
+
let panelOpen = false;
|
|
94
|
+
let pendingAction = null;
|
|
95
|
+
let localError = null;
|
|
96
|
+
let removeDocumentKeydown = null;
|
|
97
|
+
const onDocumentKeydown = (event) => {
|
|
98
|
+
if (event.key !== 'Escape' || !panelOpen)
|
|
99
|
+
return;
|
|
100
|
+
event.preventDefault();
|
|
101
|
+
event.stopPropagation();
|
|
102
|
+
closePanel(true);
|
|
103
|
+
};
|
|
104
|
+
const openPanel = () => {
|
|
105
|
+
if (destroyed || panelOpen)
|
|
106
|
+
return;
|
|
107
|
+
panelOpen = true;
|
|
108
|
+
panel.hidden = false;
|
|
109
|
+
trigger.setAttribute('aria-expanded', 'true');
|
|
110
|
+
document.addEventListener('keydown', onDocumentKeydown, true);
|
|
111
|
+
removeDocumentKeydown = () => {
|
|
112
|
+
document.removeEventListener('keydown', onDocumentKeydown, true);
|
|
113
|
+
};
|
|
114
|
+
close.focus();
|
|
115
|
+
};
|
|
116
|
+
function closePanel(restoreFocus) {
|
|
117
|
+
if (!panelOpen)
|
|
118
|
+
return;
|
|
119
|
+
panelOpen = false;
|
|
120
|
+
panel.hidden = true;
|
|
121
|
+
trigger.setAttribute('aria-expanded', 'false');
|
|
122
|
+
removeDocumentKeydown?.();
|
|
123
|
+
removeDocumentKeydown = null;
|
|
124
|
+
if (restoreFocus && !host.hidden)
|
|
125
|
+
trigger.focus();
|
|
126
|
+
}
|
|
127
|
+
const togglePanel = () => {
|
|
128
|
+
if (panelOpen)
|
|
129
|
+
closePanel(true);
|
|
130
|
+
else
|
|
131
|
+
openPanel();
|
|
132
|
+
};
|
|
133
|
+
const runLogin = async () => {
|
|
134
|
+
if (destroyed || pendingAction)
|
|
135
|
+
return;
|
|
136
|
+
pendingAction = 'login';
|
|
137
|
+
localError = null;
|
|
138
|
+
render(pixelume.auth.state);
|
|
139
|
+
try {
|
|
140
|
+
await pixelume.auth.login();
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
localError =
|
|
144
|
+
'Não foi possível abrir a entrada agora. Você pode continuar jogando e tentar novamente.';
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
pendingAction = null;
|
|
148
|
+
render(pixelume.auth.state);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
const runLogout = async () => {
|
|
152
|
+
if (destroyed || pendingAction)
|
|
153
|
+
return;
|
|
154
|
+
pendingAction = 'logout';
|
|
155
|
+
localError = null;
|
|
156
|
+
render(pixelume.auth.state);
|
|
157
|
+
try {
|
|
158
|
+
await pixelume.auth.logout();
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
localError =
|
|
162
|
+
'Você saiu deste jogo, mas não foi possível confirmar a revogação no servidor. Tente novamente mais tarde.';
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
pendingAction = null;
|
|
166
|
+
render(pixelume.auth.state);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
const render = (state) => {
|
|
170
|
+
if (destroyed)
|
|
171
|
+
return;
|
|
172
|
+
content.replaceChildren();
|
|
173
|
+
content.removeAttribute('aria-busy');
|
|
174
|
+
const authenticated = state.status === 'authenticated';
|
|
175
|
+
trigger.toggleAttribute('data-authenticated', authenticated);
|
|
176
|
+
trigger.setAttribute('aria-label', authenticated
|
|
177
|
+
? `Abrir conta Pixelume. Conectado como ${state.player.displayName}`
|
|
178
|
+
: 'Abrir conta Pixelume');
|
|
179
|
+
if (state.status === 'uninitialized' ||
|
|
180
|
+
state.status === 'redirecting' ||
|
|
181
|
+
state.status === 'exchanging') {
|
|
182
|
+
renderLoading(document, content, state.status);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (state.status === 'authenticated') {
|
|
186
|
+
const identity = document.createElement('div');
|
|
187
|
+
identity.className = 'identity';
|
|
188
|
+
const avatar = document.createElement('span');
|
|
189
|
+
avatar.className = 'avatar';
|
|
190
|
+
avatar.setAttribute('aria-hidden', 'true');
|
|
191
|
+
avatar.textContent = playerInitial(state.player.displayName);
|
|
192
|
+
const copy = document.createElement('div');
|
|
193
|
+
copy.className = 'state-copy';
|
|
194
|
+
copy.append(textElement(document, 'p', 'title', `Olá, ${state.player.displayName}!`), textElement(document, 'p', 'message', 'Sua conta está conectada a este jogo.'));
|
|
195
|
+
identity.append(avatar, copy);
|
|
196
|
+
content.append(identity);
|
|
197
|
+
if (localError)
|
|
198
|
+
content.append(notice(document, localError));
|
|
199
|
+
const logout = button(document, 'action secondary', 'Sair da conta Pixelume neste jogo');
|
|
200
|
+
logout.type = 'button';
|
|
201
|
+
logout.textContent = pendingAction === 'logout' ? 'Saindo…' : 'Sair deste jogo';
|
|
202
|
+
logout.disabled = pendingAction !== null;
|
|
203
|
+
logout.addEventListener('click', () => void runLogout());
|
|
204
|
+
content.append(logout);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const copy = document.createElement('div');
|
|
208
|
+
copy.className = 'state-copy';
|
|
209
|
+
copy.append(textElement(document, 'p', 'title', anonymousTitle(state)), textElement(document, 'p', 'message', anonymousMessage(state)));
|
|
210
|
+
content.append(copy);
|
|
211
|
+
if (state.error || localError) {
|
|
212
|
+
content.append(notice(document, localError ??
|
|
213
|
+
'Não foi possível verificar sua conta. Você pode continuar jogando e tentar novamente.'));
|
|
214
|
+
}
|
|
215
|
+
const login = button(document, 'action', 'Entrar com Pixelume');
|
|
216
|
+
login.type = 'button';
|
|
217
|
+
login.textContent = pendingAction === 'login' ? 'Abrindo Pixelume…' : 'Entrar com Pixelume';
|
|
218
|
+
login.disabled = pendingAction !== null;
|
|
219
|
+
login.addEventListener('click', () => void runLogin());
|
|
220
|
+
content.append(login);
|
|
221
|
+
};
|
|
222
|
+
const unsubscribe = pixelume.auth.subscribe((state) => {
|
|
223
|
+
localError = null;
|
|
224
|
+
render(state);
|
|
225
|
+
});
|
|
226
|
+
const stopInputPropagation = (event) => {
|
|
227
|
+
event.stopPropagation();
|
|
228
|
+
};
|
|
229
|
+
const closeFromButton = () => {
|
|
230
|
+
closePanel(true);
|
|
231
|
+
};
|
|
232
|
+
const isolatedEvents = [
|
|
233
|
+
'click',
|
|
234
|
+
'pointerdown',
|
|
235
|
+
'pointerup',
|
|
236
|
+
'touchstart',
|
|
237
|
+
'touchend',
|
|
238
|
+
'keydown',
|
|
239
|
+
'keyup',
|
|
240
|
+
];
|
|
241
|
+
for (const eventName of isolatedEvents)
|
|
242
|
+
host.addEventListener(eventName, stopInputPropagation);
|
|
243
|
+
trigger.addEventListener('click', togglePanel);
|
|
244
|
+
close.addEventListener('click', closeFromButton);
|
|
245
|
+
const controller = Object.freeze({
|
|
246
|
+
element: host,
|
|
247
|
+
hide() {
|
|
248
|
+
if (destroyed)
|
|
249
|
+
return;
|
|
250
|
+
closePanel(false);
|
|
251
|
+
host.hidden = true;
|
|
252
|
+
},
|
|
253
|
+
show() {
|
|
254
|
+
if (destroyed)
|
|
255
|
+
return;
|
|
256
|
+
host.hidden = false;
|
|
257
|
+
},
|
|
258
|
+
destroy() {
|
|
259
|
+
if (destroyed)
|
|
260
|
+
return;
|
|
261
|
+
destroyed = true;
|
|
262
|
+
closePanel(false);
|
|
263
|
+
removeDocumentKeydown?.();
|
|
264
|
+
removeDocumentKeydown = null;
|
|
265
|
+
unsubscribe();
|
|
266
|
+
trigger.removeEventListener('click', togglePanel);
|
|
267
|
+
close.removeEventListener('click', closeFromButton);
|
|
268
|
+
for (const eventName of isolatedEvents)
|
|
269
|
+
host.removeEventListener(eventName, stopInputPropagation);
|
|
270
|
+
host.remove();
|
|
271
|
+
widgetsByClient.delete(pixelume);
|
|
272
|
+
widgetsByContainer.delete(container);
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
render(pixelume.auth.state);
|
|
276
|
+
container.append(host);
|
|
277
|
+
widgetsByClient.set(pixelume, { container, controller });
|
|
278
|
+
widgetsByContainer.set(container, pixelume);
|
|
279
|
+
return controller;
|
|
280
|
+
}
|
|
281
|
+
function assertClient(value) {
|
|
282
|
+
if (typeof value !== 'object' || value === null)
|
|
283
|
+
throw new TypeError('Pixelume widget requires a client');
|
|
284
|
+
const auth = Reflect.get(value, 'auth');
|
|
285
|
+
if (typeof auth !== 'object' || auth === null)
|
|
286
|
+
throw new TypeError('Pixelume widget requires client.auth');
|
|
287
|
+
for (const method of ['login', 'logout', 'subscribe']) {
|
|
288
|
+
if (typeof Reflect.get(auth, method) !== 'function') {
|
|
289
|
+
throw new TypeError(`Pixelume widget requires client.auth.${method}()`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function resolveDocument(container) {
|
|
294
|
+
if (container) {
|
|
295
|
+
if (typeof container.attachShadow !== 'function') {
|
|
296
|
+
throw new TypeError('Pixelume widget container must be an HTMLElement');
|
|
297
|
+
}
|
|
298
|
+
return container.ownerDocument;
|
|
299
|
+
}
|
|
300
|
+
const candidate = Reflect.get(globalThis, 'document');
|
|
301
|
+
if (typeof candidate !== 'object' || candidate === null || !('createElement' in candidate)) {
|
|
302
|
+
throw new Error('Pixelume widget can only be mounted in a browser document');
|
|
303
|
+
}
|
|
304
|
+
return candidate;
|
|
305
|
+
}
|
|
306
|
+
function resolvePosition(value) {
|
|
307
|
+
if (value === undefined)
|
|
308
|
+
return DEFAULT_POSITION;
|
|
309
|
+
if (!POSITIONS.includes(value)) {
|
|
310
|
+
throw new Error(`Pixelume widget position must be one of: ${POSITIONS.join(', ')}`);
|
|
311
|
+
}
|
|
312
|
+
return value;
|
|
313
|
+
}
|
|
314
|
+
function resolveNumber(name, value, fallback, minimum, maximum) {
|
|
315
|
+
if (value === undefined)
|
|
316
|
+
return fallback;
|
|
317
|
+
if (!Number.isInteger(value) || value < minimum || value > maximum) {
|
|
318
|
+
throw new Error(`Pixelume widget ${name} must be an integer from ${minimum} to ${maximum}`);
|
|
319
|
+
}
|
|
320
|
+
return value;
|
|
321
|
+
}
|
|
322
|
+
function button(document, className, label) {
|
|
323
|
+
const element = document.createElement('button');
|
|
324
|
+
element.className = className;
|
|
325
|
+
element.setAttribute('aria-label', label);
|
|
326
|
+
return element;
|
|
327
|
+
}
|
|
328
|
+
function textElement(document, tag, className, text) {
|
|
329
|
+
const element = document.createElement(tag);
|
|
330
|
+
element.className = className;
|
|
331
|
+
element.textContent = text;
|
|
332
|
+
return element;
|
|
333
|
+
}
|
|
334
|
+
function notice(document, text) {
|
|
335
|
+
const element = textElement(document, 'p', 'notice', text);
|
|
336
|
+
element.setAttribute('role', 'alert');
|
|
337
|
+
return element;
|
|
338
|
+
}
|
|
339
|
+
function renderLoading(document, content, status) {
|
|
340
|
+
const labels = {
|
|
341
|
+
uninitialized: 'Preparando sua conta…',
|
|
342
|
+
redirecting: 'Abrindo o Pixelume Auth…',
|
|
343
|
+
exchanging: 'Concluindo a entrada…',
|
|
344
|
+
};
|
|
345
|
+
content.setAttribute('aria-busy', 'true');
|
|
346
|
+
const visual = document.createElement('div');
|
|
347
|
+
visual.className = 'loading';
|
|
348
|
+
visual.setAttribute('aria-hidden', 'true');
|
|
349
|
+
for (let index = 0; index < 2; index += 1) {
|
|
350
|
+
const line = document.createElement('span');
|
|
351
|
+
line.className = 'loading-line';
|
|
352
|
+
visual.append(line);
|
|
353
|
+
}
|
|
354
|
+
const label = textElement(document, 'p', 'sr-only', labels[status]);
|
|
355
|
+
content.append(visual, label);
|
|
356
|
+
}
|
|
357
|
+
function playerInitial(displayName) {
|
|
358
|
+
return Array.from(displayName.trim())[0]?.toLocaleUpperCase('pt-BR') ?? 'P';
|
|
359
|
+
}
|
|
360
|
+
function anonymousTitle(state) {
|
|
361
|
+
if (state.reason === 'logged_out')
|
|
362
|
+
return 'Você saiu deste jogo';
|
|
363
|
+
if (state.reason === 'expired')
|
|
364
|
+
return 'Sua sessão expirou';
|
|
365
|
+
if (state.reason === 'cancelled')
|
|
366
|
+
return 'Entrada cancelada';
|
|
367
|
+
return 'Sua conta Pixelume';
|
|
368
|
+
}
|
|
369
|
+
function anonymousMessage(state) {
|
|
370
|
+
if (state.reason === 'logged_out')
|
|
371
|
+
return 'Entre novamente quando quiser.';
|
|
372
|
+
if (state.reason === 'expired')
|
|
373
|
+
return 'Entre novamente para continuar com sua conta.';
|
|
374
|
+
if (state.reason === 'cancelled')
|
|
375
|
+
return 'Você pode continuar como visitante ou tentar novamente.';
|
|
376
|
+
return 'Entre pelo portal seguro da Pixelume. Sua senha nunca passa pelo jogo.';
|
|
377
|
+
}
|
|
378
|
+
//# sourceMappingURL=widget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widget.js","sourceRoot":"","sources":["../../src/ui/widget.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PixelumeClient } from '../core/PixelumeClient.js';\nimport type { PixelumeAuthState } from '../modules/auth/AuthModule.js';\nimport { WIDGET_STYLES } from './styles.js';\n\nexport type PixelumeWidgetPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n\nexport interface PixelumeWidgetOptions {\n /** Corner used by the widget. Defaults to `bottom-right`. */\n readonly position?: PixelumeWidgetPosition;\n /** Distance from the selected edges in CSS pixels. Defaults to `16`. */\n readonly offset?: number;\n /** Mount target. Defaults to `document.body`; custom targets should establish a containing block. */\n readonly container?: HTMLElement;\n /** Visual treatment. `pixel` is currently the only supported theme. */\n readonly theme?: 'pixel';\n /** Stacking order for the host. Defaults to `2147483000`. */\n readonly zIndex?: number;\n}\n\nexport interface PixelumeWidgetController {\n /** The Shadow DOM host created by the widget. */\n readonly element: HTMLElement;\n /** Hides the widget and closes its panel without changing authentication state. */\n hide(): void;\n /** Shows a previously hidden widget. */\n show(): void;\n /** Removes DOM/listeners/subscriptions. Safe to call more than once. */\n destroy(): void;\n}\n\nconst DEFAULT_POSITION: PixelumeWidgetPosition = 'bottom-right';\nconst DEFAULT_OFFSET = 16;\nconst DEFAULT_Z_INDEX = 2_147_483_000;\nconst POSITIONS: readonly PixelumeWidgetPosition[] = [\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n];\n\ninterface MountedWidget {\n readonly container: HTMLElement;\n readonly controller: PixelumeWidgetController;\n}\n\nconst widgetsByClient = new WeakMap<object, MountedWidget>();\nconst widgetsByContainer = new WeakMap<HTMLElement, object>();\nlet nextWidgetId = 1;\n\n/**\n * Mounts the optional Pixelume account widget. Importing this module alone has no DOM side effects.\n * Repeating the call with the same client and container returns the existing controller.\n */\nexport function mountPixelumeWidget(\n pixelume: PixelumeClient,\n options: PixelumeWidgetOptions = {},\n): PixelumeWidgetController {\n assertClient(pixelume);\n const document = resolveDocument(options.container);\n const container = options.container ?? document.body;\n\n const mounted = widgetsByClient.get(pixelume);\n if (mounted) {\n if (mounted.container === container) return mounted.controller;\n throw new Error('This Pixelume client already has a widget mounted in another container');\n }\n const containerOwner = widgetsByContainer.get(container);\n if (containerOwner) {\n throw new Error('This container already has a Pixelume widget mounted');\n }\n\n const position = resolvePosition(options.position);\n const offset = resolveNumber('offset', options.offset, DEFAULT_OFFSET, 0, 256);\n const zIndex = resolveNumber('zIndex', options.zIndex, DEFAULT_Z_INDEX, 0, 2_147_483_647);\n const theme: unknown = options.theme;\n if (theme !== undefined && theme !== 'pixel') {\n throw new Error('Pixelume widget theme must be \"pixel\"');\n }\n\n const host = document.createElement('div');\n host.dataset.pixelumeWidget = '';\n host.dataset.position = position;\n host.style.setProperty('--pixelume-offset', `${offset}px`);\n host.style.setProperty('--pixelume-z-index', String(zIndex));\n if (options.container) host.dataset.contained = '';\n\n const shadow = host.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = WIDGET_STYLES;\n\n const root = document.createElement('div');\n root.className = 'root';\n\n const panelId = `pixelume-widget-panel-${nextWidgetId++}`;\n const trigger = button(document, 'trigger', 'Abrir conta Pixelume');\n trigger.type = 'button';\n trigger.setAttribute('aria-expanded', 'false');\n trigger.setAttribute('aria-controls', panelId);\n const triggerMark = document.createElement('span');\n triggerMark.className = 'mark';\n triggerMark.setAttribute('aria-hidden', 'true');\n const triggerLabel = document.createElement('span');\n triggerLabel.className = 'trigger-label';\n triggerLabel.textContent = 'Pixelume';\n const presence = document.createElement('span');\n presence.className = 'presence';\n presence.setAttribute('aria-hidden', 'true');\n trigger.append(triggerMark, triggerLabel, presence);\n\n const panel = document.createElement('section');\n panel.className = 'panel';\n panel.id = panelId;\n panel.hidden = true;\n panel.setAttribute('aria-label', 'Conta Pixelume');\n panel.setAttribute('aria-live', 'polite');\n\n const header = document.createElement('div');\n header.className = 'panel-header';\n const brand = document.createElement('span');\n brand.className = 'brand';\n const brandMark = document.createElement('span');\n brandMark.className = 'mark';\n brandMark.setAttribute('aria-hidden', 'true');\n const brandText = document.createElement('span');\n brandText.textContent = 'Pixelume';\n brand.append(brandMark, brandText);\n const close = button(document, 'close', 'Fechar painel da conta');\n close.type = 'button';\n close.textContent = '×';\n close.setAttribute('aria-hidden', 'false');\n header.append(brand, close);\n\n const content = document.createElement('div');\n content.className = 'content';\n panel.append(header, content);\n root.append(trigger, panel);\n shadow.append(style, root);\n\n let destroyed = false;\n let panelOpen = false;\n let pendingAction: 'login' | 'logout' | null = null;\n let localError: string | null = null;\n let removeDocumentKeydown: (() => void) | null = null;\n\n const onDocumentKeydown = (event: KeyboardEvent): void => {\n if (event.key !== 'Escape' || !panelOpen) return;\n event.preventDefault();\n event.stopPropagation();\n closePanel(true);\n };\n\n const openPanel = (): void => {\n if (destroyed || panelOpen) return;\n panelOpen = true;\n panel.hidden = false;\n trigger.setAttribute('aria-expanded', 'true');\n document.addEventListener('keydown', onDocumentKeydown, true);\n removeDocumentKeydown = () => {\n document.removeEventListener('keydown', onDocumentKeydown, true);\n };\n close.focus();\n };\n\n function closePanel(restoreFocus: boolean): void {\n if (!panelOpen) return;\n panelOpen = false;\n panel.hidden = true;\n trigger.setAttribute('aria-expanded', 'false');\n removeDocumentKeydown?.();\n removeDocumentKeydown = null;\n if (restoreFocus && !host.hidden) trigger.focus();\n }\n\n const togglePanel = (): void => {\n if (panelOpen) closePanel(true);\n else openPanel();\n };\n\n const runLogin = async (): Promise<void> => {\n if (destroyed || pendingAction) return;\n pendingAction = 'login';\n localError = null;\n render(pixelume.auth.state);\n try {\n await pixelume.auth.login();\n } catch {\n localError =\n 'Não foi possível abrir a entrada agora. Você pode continuar jogando e tentar novamente.';\n } finally {\n pendingAction = null;\n render(pixelume.auth.state);\n }\n };\n\n const runLogout = async (): Promise<void> => {\n if (destroyed || pendingAction) return;\n pendingAction = 'logout';\n localError = null;\n render(pixelume.auth.state);\n try {\n await pixelume.auth.logout();\n } catch {\n localError =\n 'Você saiu deste jogo, mas não foi possível confirmar a revogação no servidor. Tente novamente mais tarde.';\n } finally {\n pendingAction = null;\n render(pixelume.auth.state);\n }\n };\n\n const render = (state: PixelumeAuthState): void => {\n if (destroyed) return;\n content.replaceChildren();\n content.removeAttribute('aria-busy');\n const authenticated = state.status === 'authenticated';\n trigger.toggleAttribute('data-authenticated', authenticated);\n trigger.setAttribute(\n 'aria-label',\n authenticated\n ? `Abrir conta Pixelume. Conectado como ${state.player.displayName}`\n : 'Abrir conta Pixelume',\n );\n\n if (\n state.status === 'uninitialized' ||\n state.status === 'redirecting' ||\n state.status === 'exchanging'\n ) {\n renderLoading(document, content, state.status);\n return;\n }\n\n if (state.status === 'authenticated') {\n const identity = document.createElement('div');\n identity.className = 'identity';\n const avatar = document.createElement('span');\n avatar.className = 'avatar';\n avatar.setAttribute('aria-hidden', 'true');\n avatar.textContent = playerInitial(state.player.displayName);\n const copy = document.createElement('div');\n copy.className = 'state-copy';\n copy.append(\n textElement(document, 'p', 'title', `Olá, ${state.player.displayName}!`),\n textElement(document, 'p', 'message', 'Sua conta está conectada a este jogo.'),\n );\n identity.append(avatar, copy);\n content.append(identity);\n if (localError) content.append(notice(document, localError));\n const logout = button(document, 'action secondary', 'Sair da conta Pixelume neste jogo');\n logout.type = 'button';\n logout.textContent = pendingAction === 'logout' ? 'Saindo…' : 'Sair deste jogo';\n logout.disabled = pendingAction !== null;\n logout.addEventListener('click', () => void runLogout());\n content.append(logout);\n return;\n }\n\n const copy = document.createElement('div');\n copy.className = 'state-copy';\n copy.append(\n textElement(document, 'p', 'title', anonymousTitle(state)),\n textElement(document, 'p', 'message', anonymousMessage(state)),\n );\n content.append(copy);\n if (state.error || localError) {\n content.append(\n notice(\n document,\n localError ??\n 'Não foi possível verificar sua conta. Você pode continuar jogando e tentar novamente.',\n ),\n );\n }\n const login = button(document, 'action', 'Entrar com Pixelume');\n login.type = 'button';\n login.textContent = pendingAction === 'login' ? 'Abrindo Pixelume…' : 'Entrar com Pixelume';\n login.disabled = pendingAction !== null;\n login.addEventListener('click', () => void runLogin());\n content.append(login);\n };\n\n const unsubscribe = pixelume.auth.subscribe((state) => {\n localError = null;\n render(state);\n });\n\n const stopInputPropagation = (event: Event): void => {\n event.stopPropagation();\n };\n const closeFromButton = (): void => {\n closePanel(true);\n };\n const isolatedEvents = [\n 'click',\n 'pointerdown',\n 'pointerup',\n 'touchstart',\n 'touchend',\n 'keydown',\n 'keyup',\n ] as const;\n for (const eventName of isolatedEvents) host.addEventListener(eventName, stopInputPropagation);\n trigger.addEventListener('click', togglePanel);\n close.addEventListener('click', closeFromButton);\n\n const controller: PixelumeWidgetController = Object.freeze({\n element: host,\n hide(): void {\n if (destroyed) return;\n closePanel(false);\n host.hidden = true;\n },\n show(): void {\n if (destroyed) return;\n host.hidden = false;\n },\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n closePanel(false);\n removeDocumentKeydown?.();\n removeDocumentKeydown = null;\n unsubscribe();\n trigger.removeEventListener('click', togglePanel);\n close.removeEventListener('click', closeFromButton);\n for (const eventName of isolatedEvents)\n host.removeEventListener(eventName, stopInputPropagation);\n host.remove();\n widgetsByClient.delete(pixelume);\n widgetsByContainer.delete(container);\n },\n });\n\n render(pixelume.auth.state);\n container.append(host);\n widgetsByClient.set(pixelume, { container, controller });\n widgetsByContainer.set(container, pixelume);\n return controller;\n}\n\nfunction assertClient(value: unknown): asserts value is PixelumeClient {\n if (typeof value !== 'object' || value === null)\n throw new TypeError('Pixelume widget requires a client');\n const auth = Reflect.get(value, 'auth') as unknown;\n if (typeof auth !== 'object' || auth === null)\n throw new TypeError('Pixelume widget requires client.auth');\n for (const method of ['login', 'logout', 'subscribe'] as const) {\n if (typeof Reflect.get(auth, method) !== 'function') {\n throw new TypeError(`Pixelume widget requires client.auth.${method}()`);\n }\n }\n}\n\nfunction resolveDocument(container: HTMLElement | undefined): Document {\n if (container) {\n if (typeof container.attachShadow !== 'function') {\n throw new TypeError('Pixelume widget container must be an HTMLElement');\n }\n return container.ownerDocument;\n }\n const candidate = Reflect.get(globalThis, 'document') as unknown;\n if (typeof candidate !== 'object' || candidate === null || !('createElement' in candidate)) {\n throw new Error('Pixelume widget can only be mounted in a browser document');\n }\n return candidate as Document;\n}\n\nfunction resolvePosition(value: PixelumeWidgetPosition | undefined): PixelumeWidgetPosition {\n if (value === undefined) return DEFAULT_POSITION;\n if (!POSITIONS.includes(value)) {\n throw new Error(`Pixelume widget position must be one of: ${POSITIONS.join(', ')}`);\n }\n return value;\n}\n\nfunction resolveNumber(\n name: string,\n value: number | undefined,\n fallback: number,\n minimum: number,\n maximum: number,\n): number {\n if (value === undefined) return fallback;\n if (!Number.isInteger(value) || value < minimum || value > maximum) {\n throw new Error(`Pixelume widget ${name} must be an integer from ${minimum} to ${maximum}`);\n }\n return value;\n}\n\nfunction button(document: Document, className: string, label: string): HTMLButtonElement {\n const element = document.createElement('button');\n element.className = className;\n element.setAttribute('aria-label', label);\n return element;\n}\n\nfunction textElement(\n document: Document,\n tag: 'p',\n className: string,\n text: string,\n): HTMLParagraphElement {\n const element = document.createElement(tag);\n element.className = className;\n element.textContent = text;\n return element;\n}\n\nfunction notice(document: Document, text: string): HTMLParagraphElement {\n const element = textElement(document, 'p', 'notice', text);\n element.setAttribute('role', 'alert');\n return element;\n}\n\nfunction renderLoading(\n document: Document,\n content: HTMLElement,\n status: 'uninitialized' | 'redirecting' | 'exchanging',\n): void {\n const labels = {\n uninitialized: 'Preparando sua conta…',\n redirecting: 'Abrindo o Pixelume Auth…',\n exchanging: 'Concluindo a entrada…',\n } as const;\n content.setAttribute('aria-busy', 'true');\n const visual = document.createElement('div');\n visual.className = 'loading';\n visual.setAttribute('aria-hidden', 'true');\n for (let index = 0; index < 2; index += 1) {\n const line = document.createElement('span');\n line.className = 'loading-line';\n visual.append(line);\n }\n const label = textElement(document, 'p', 'sr-only', labels[status]);\n content.append(visual, label);\n}\n\nfunction playerInitial(displayName: string): string {\n return Array.from(displayName.trim())[0]?.toLocaleUpperCase('pt-BR') ?? 'P';\n}\n\nfunction anonymousTitle(state: Extract<PixelumeAuthState, { status: 'anonymous' }>): string {\n if (state.reason === 'logged_out') return 'Você saiu deste jogo';\n if (state.reason === 'expired') return 'Sua sessão expirou';\n if (state.reason === 'cancelled') return 'Entrada cancelada';\n return 'Sua conta Pixelume';\n}\n\nfunction anonymousMessage(state: Extract<PixelumeAuthState, { status: 'anonymous' }>): string {\n if (state.reason === 'logged_out') return 'Entre novamente quando quiser.';\n if (state.reason === 'expired') return 'Entre novamente para continuar com sua conta.';\n if (state.reason === 'cancelled')\n return 'Você pode continuar como visitante ou tentar novamente.';\n return 'Entre pelo portal seguro da Pixelume. Sua senha nunca passa pelo jogo.';\n}\n"]}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Version of the SDK package. Kept in sync with `package.json` (checked by tests and by the release workflow). */
|
|
2
|
-
export declare const SDK_VERSION = "0.
|
|
2
|
+
export declare const SDK_VERSION = "0.3.0";
|
package/dist/version.js
CHANGED
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,mHAAmH;AACnH,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC","sourcesContent":["/** Version of the SDK package. Kept in sync with `package.json` (checked by tests and by the release workflow). */\nexport const SDK_VERSION = '0.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,mHAAmH;AACnH,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC","sourcesContent":["/** Version of the SDK package. Kept in sync with `package.json` (checked by tests and by the release workflow). */\nexport const SDK_VERSION = '0.3.0';\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixelume/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "SDK TypeScript da Pixelume para jogos web: SSO com PKCE e
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "SDK TypeScript da Pixelume para jogos web: core headless, SSO com PKCE e widget oficial opcional.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Erickson Nascimento",
|
|
7
7
|
"repository": {
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"types": "./dist/index.d.ts",
|
|
26
26
|
"import": "./dist/index.js"
|
|
27
27
|
},
|
|
28
|
+
"./ui": {
|
|
29
|
+
"types": "./dist/ui/index.d.ts",
|
|
30
|
+
"import": "./dist/ui/index.js"
|
|
31
|
+
},
|
|
28
32
|
"./package.json": "./package.json"
|
|
29
33
|
},
|
|
30
34
|
"types": "./dist/index.d.ts",
|
|
@@ -61,6 +65,7 @@
|
|
|
61
65
|
"@eslint/js": "10.0.1",
|
|
62
66
|
"@types/node": "^24.10.1",
|
|
63
67
|
"eslint": "10.12.0",
|
|
68
|
+
"happy-dom": "21.0.1",
|
|
64
69
|
"prettier": "3.9.10",
|
|
65
70
|
"publint": "0.3.25",
|
|
66
71
|
"typescript": "6.0.3",
|