@atlasauth/svelte 0.1.5 → 0.2.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.
@@ -17,6 +17,9 @@
17
17
  * replacement is a support burden where every override starts by rebuilding the
18
18
  * component's base styles from scratch.
19
19
  */
20
+ import { type AppearanceRender, type DesignAppearance, type DesignWarn, type InstanceDesign } from '@atlasauth/design/runtime';
21
+ export { instanceDesignFrom } from '@atlasauth/design/runtime';
22
+ export type { AppearanceRender, AtlasDesign, InstanceDesign, PresetId } from '@atlasauth/design/runtime';
20
23
  export interface DesignTokens {
21
24
  colorPrimary?: string;
22
25
  colorText?: string;
@@ -29,9 +32,13 @@ export interface DesignTokens {
29
32
  }
30
33
  /** Every element a customer may target. Named for what it IS, not where it sits. */
31
34
  export type ElementKey = 'root' | 'card' | 'headerTitle' | 'headerSubtitle' | 'formField' | 'formFieldLabel' | 'formFieldInput' | 'formFieldError' | 'formButtonPrimary' | 'formButtonSecondary' | 'socialButton' | 'dividerText' | 'footerAction' | 'avatar' | 'menu' | 'menuItem' | 'badge';
32
- export interface Appearance {
33
- /** A prebuilt theme to start from. */
35
+ export interface Appearance extends DesignAppearance {
36
+ /** A prebuilt token theme to start from (pre-design-system themes). */
34
37
  baseTheme?: keyof typeof THEMES;
38
+ /**
39
+ * Legacy design tokens. Without a design they set the `--atlas-*` variables
40
+ * exactly as before; with one they map onto it.
41
+ */
35
42
  variables?: DesignTokens;
36
43
  elements?: Partial<Record<ElementKey, string>>;
37
44
  }
@@ -83,3 +90,21 @@ export declare function cssVariables(tokens: Required<DesignTokens>): Record<str
83
90
  * specificity, which is the behaviour anyone writing Tailwind expects.
84
91
  */
85
92
  export declare function classFor(element: ElementKey, appearance: Appearance | undefined, base: string): string;
93
+ /**
94
+ * The legacy tokens the developer chose EXPLICITLY: a non-default `baseTheme`
95
+ * plus `variables`. Only these map onto a design — the token defaults must not
96
+ * overwrite the dashboard design.
97
+ */
98
+ export declare function explicitTokens(appearance?: Appearance): DesignTokens;
99
+ /**
100
+ * Turn an `appearance` (+ the instance's dashboard design from the Frontend
101
+ * API) into root attributes and a stylesheet — the same semantics as
102
+ * `@atlasauth/react`. Precedence, lowest first: dashboard design < `preset` <
103
+ * `variables` (and a non-default `baseTheme`) < `design`. Without a dashboard
104
+ * design and without `preset`/`design`, the output is exactly the
105
+ * pre-design-system one: the token variables, no stylesheet, no attributes.
106
+ */
107
+ export declare function renderAppearance(appearance: Appearance | undefined, instanceDesign: InstanceDesign | null | undefined, options?: {
108
+ frontendApi?: string;
109
+ warn?: DesignWarn;
110
+ }): AppearanceRender;
@@ -17,6 +17,8 @@
17
17
  * replacement is a support burden where every override starts by rebuilding the
18
18
  * component's base styles from scratch.
19
19
  */
20
+ import { renderDesignAppearance, } from '@atlasauth/design/runtime';
21
+ export { instanceDesignFrom } from '@atlasauth/design/runtime';
20
22
  export const DEFAULT_TOKENS = {
21
23
  colorPrimary: '#5b5bd6',
22
24
  colorText: '#1c1c1f',
@@ -89,3 +91,36 @@ export function classFor(element, appearance, base) {
89
91
  const override = appearance?.elements?.[element];
90
92
  return override ? `${base} ${override}` : base;
91
93
  }
94
+ // ---- the design system ---------------------------------------------------------
95
+ /**
96
+ * The legacy tokens the developer chose EXPLICITLY: a non-default `baseTheme`
97
+ * plus `variables`. Only these map onto a design — the token defaults must not
98
+ * overwrite the dashboard design.
99
+ */
100
+ export function explicitTokens(appearance) {
101
+ const out = {};
102
+ if (appearance?.baseTheme && appearance.baseTheme !== 'default') {
103
+ Object.assign(out, THEMES[appearance.baseTheme]);
104
+ }
105
+ for (const [key, value] of Object.entries(appearance?.variables ?? {})) {
106
+ if (value !== undefined)
107
+ out[key] = value;
108
+ }
109
+ return out;
110
+ }
111
+ /**
112
+ * Turn an `appearance` (+ the instance's dashboard design from the Frontend
113
+ * API) into root attributes and a stylesheet — the same semantics as
114
+ * `@atlasauth/react`. Precedence, lowest first: dashboard design < `preset` <
115
+ * `variables` (and a non-default `baseTheme`) < `design`. Without a dashboard
116
+ * design and without `preset`/`design`, the output is exactly the
117
+ * pre-design-system one: the token variables, no stylesheet, no attributes.
118
+ */
119
+ export function renderAppearance(appearance, instanceDesign, options = {}) {
120
+ return renderDesignAppearance(appearance, instanceDesign, {
121
+ tokens: explicitTokens(appearance),
122
+ legacyStyle: () => cssVariables(resolveTokens(appearance)),
123
+ frontendApi: options.frontendApi,
124
+ warn: options.warn,
125
+ });
126
+ }
@@ -1,6 +1,6 @@
1
1
  <script>import { onDestroy, onMount } from "svelte";
2
2
  import { initAtlas } from "../context";
3
- import { cssVariables, resolveTokens } from "../appearance";
3
+ import { renderAppearance } from "../appearance";
4
4
  export let publishableKey;
5
5
  export let frontendApi = void 0;
6
6
  export let appearance = void 0;
@@ -13,11 +13,28 @@ const client = initAtlas({
13
13
  localization,
14
14
  fetchImpl
15
15
  });
16
- $: style = Object.entries(cssVariables(resolveTokens(appearance))).map(([name, value]) => `${name}: ${value}`).join("; ");
17
- onMount(() => void client.boot());
16
+ let instanceDesign = null;
17
+ $: rendered = renderAppearance(appearance, instanceDesign, { frontendApi });
18
+ $: style = Object.entries(rendered.style).map(([name, value]) => `${name}: ${value}`).join("; ");
19
+ $: designStyle = rendered.css ? `<style data-atlas-design="${rendered.key}">${rendered.css}</style>` : "";
20
+ onMount(() => {
21
+ void client.boot();
22
+ if (appearance?.instanceDesign !== false) {
23
+ void client.loadInstanceDesign().then((design) => {
24
+ if (design) instanceDesign = design;
25
+ });
26
+ }
27
+ });
18
28
  onDestroy(() => client.destroy());
19
29
  </script>
20
30
 
21
- <div class="atlas-root" {style}>
31
+ <svelte:head>
32
+ {@html designStyle}
33
+ {#each rendered.fontStylesheets as href (href)}
34
+ <link rel="stylesheet" {href} data-atlas-font="" />
35
+ {/each}
36
+ </svelte:head>
37
+
38
+ <div class="atlas-root" {style} {...rendered.attributes}>
22
39
  <slot />
23
40
  </div>
package/dist/context.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type Readable } from 'svelte/store';
2
2
  import { type ProviderToken } from '@atlasauth/js';
3
3
  import { type Catalog } from './i18n';
4
- import type { Appearance } from './appearance';
4
+ import { type Appearance, type InstanceDesign } from './appearance';
5
5
  import type { AtlasOrganizationMembership, AtlasSession, AtlasUser, SessionClaims } from './types';
6
6
  /**
7
7
  * §10.1 the Svelte peer of React's `<AtlasProvider>`.
@@ -80,6 +80,11 @@ export interface AtlasClient extends AtlasStores {
80
80
  * `<AtlasProvider>` also calls it in `onMount`, and a second call is a no-op.
81
81
  */
82
82
  boot(): Promise<void>;
83
+ /**
84
+ * The design configured in the Atlas dashboard (`GET /v1/appearance`), or null
85
+ * when there is none or it cannot be read. `<AtlasProvider>` applies it.
86
+ */
87
+ loadInstanceDesign(): Promise<InstanceDesign | null>;
83
88
  /** Cancel the scheduled refresh — call from a component's `onDestroy`. */
84
89
  destroy(): void;
85
90
  }
package/dist/context.js CHANGED
@@ -2,6 +2,7 @@ import { getContext, setContext } from 'svelte';
2
2
  import { derived, get, writable } from 'svelte/store';
3
3
  import { FapiClient, TokenCache, getProviderToken as fetchProviderToken, msUntilRefresh, readExpiry, readRedirectResult, stripRedirectParams, } from '@atlasauth/js';
4
4
  import { EN_US, withFallback } from './i18n';
5
+ import { instanceDesignFrom } from './appearance';
5
6
  /** The context key. A `Symbol` so it cannot collide with an app's own context. */
6
7
  export const ATLAS_KEY = Symbol('atlas');
7
8
  function decodeClaims(jwt) {
@@ -196,6 +197,15 @@ export function createAtlasClient(options) {
196
197
  }
197
198
  await reload();
198
199
  }
200
+ async function loadInstanceDesign() {
201
+ try {
202
+ const response = await call('/v1/appearance');
203
+ return response.ok ? instanceDesignFrom(await response.json()) : null;
204
+ }
205
+ catch {
206
+ return null;
207
+ }
208
+ }
199
209
  function destroy() {
200
210
  if (timer)
201
211
  clearTimeout(timer);
@@ -222,6 +232,7 @@ export function createAtlasClient(options) {
222
232
  setActiveOrganization,
223
233
  reload,
224
234
  boot,
235
+ loadInstanceDesign,
225
236
  destroy,
226
237
  };
227
238
  // Kick off the browser boot immediately unless the caller opts out. Guarded to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlasauth/svelte",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "svelte": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -21,9 +21,10 @@
21
21
  "./package.json": "./package.json"
22
22
  },
23
23
  "dependencies": {
24
+ "@atlasauth/design": "0.1.0",
25
+ "@atlasauth/authz": "0.1.1",
24
26
  "@atlasauth/js": "0.4.0",
25
- "@atlasauth/backend": "0.3.0",
26
- "@atlasauth/authz": "0.1.1"
27
+ "@atlasauth/backend": "0.3.0"
27
28
  },
28
29
  "peerDependencies": {
29
30
  "svelte": ">=4",