@xforge-dev/forge-kit 0.22.0 → 0.23.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.
@@ -1,6 +1,6 @@
1
1
  export const JOBS_SNAPSHOT = {
2
2
  "version": 1,
3
- "updated": "2026-10-29T18:30:00Z",
3
+ "updated": "2026-11-10T20:30:00Z",
4
4
  "jobs": [
5
5
  {
6
6
  "name": "Hero",
@@ -2784,7 +2784,7 @@ export const JOBS_SNAPSHOT = {
2784
2784
  "secondaryStats": [
2785
2785
  "LUK"
2786
2786
  ],
2787
- "status": "upcoming",
2787
+ "status": "released",
2788
2788
  "icon": "https://cdn.xforge.dev/classes/jobs/icons/lethe.png",
2789
2789
  "nexon": null,
2790
2790
  "legion": {
@@ -2833,7 +2833,17 @@ export const JOBS_SNAPSHOT = {
2833
2833
  "All Stats +50, Max HP +2,500"
2834
2834
  ]
2835
2835
  },
2836
- "link": null
2836
+ "link": {
2837
+ "key": "lethe",
2838
+ "name": "Covenant",
2839
+ "icon": "https://cdn.xforge.dev/links/lethe.png",
2840
+ "max": 3,
2841
+ "text": [
2842
+ "Damage +4% while a summon is active",
2843
+ "Damage +8% while a summon is active",
2844
+ "Damage +12% while a summon is active"
2845
+ ]
2846
+ }
2837
2847
  }
2838
2848
  ]
2839
2849
  };
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
4
- import { DEFAULT_THEME, THEME_COLOR_KEY, THEME_MODE_KEY, THEME_SYNC_KEY, isColorTheme, isThemeMode, parseThemeCookie, themeCookie, } from './theme.js';
4
+ import { DEFAULT_THEME, hostThemeCookieExpiry, THEME_COLOR_KEY, THEME_MODE_KEY, THEME_SYNC_KEY, isColorTheme, isThemeMode, parseThemeCookie, writeThemeCookie, } from './theme.js';
5
5
  const Context = createContext(undefined);
6
6
  function safeStorage() {
7
7
  try {
@@ -39,7 +39,7 @@ export function storeForgeTheme(theme) {
39
39
  storage?.setItem(THEME_MODE_KEY, theme.mode);
40
40
  storage?.setItem(THEME_COLOR_KEY, theme.color);
41
41
  if (readSync(storage))
42
- document.cookie = themeCookie(theme);
42
+ writeThemeCookie(theme);
43
43
  }
44
44
  function apply(theme) {
45
45
  const root = document.documentElement;
@@ -66,7 +66,7 @@ export function ForgeThemeProvider({ children, onChange }) {
66
66
  setThemeState(next);
67
67
  apply(next);
68
68
  if (share && readSync(storage))
69
- document.cookie = themeCookie(next);
69
+ writeThemeCookie(next);
70
70
  if (!same(local, next)) {
71
71
  storage?.setItem(THEME_MODE_KEY, next.mode);
72
72
  storage?.setItem(THEME_COLOR_KEY, next.color);
@@ -79,6 +79,10 @@ export function ForgeThemeProvider({ children, onChange }) {
79
79
  const storage = safeStorage();
80
80
  setSyncState(readSync(storage));
81
81
  const adopt = () => {
82
+ // A stale host-only copy would shadow the shared cookie: drop it before reading.
83
+ const expiry = hostThemeCookieExpiry();
84
+ if (expiry)
85
+ document.cookie = expiry;
82
86
  const next = resolveTheme(storage, document.cookie);
83
87
  // The first app visited seeds the shared theme for the others.
84
88
  const seed = readSync(storage) && !parseThemeCookie(document.cookie);
@@ -114,7 +118,7 @@ export function ForgeThemeProvider({ children, onChange }) {
114
118
  setSyncState(sync);
115
119
  // Turning sync on shares this app's current theme rather than jumping to another app's.
116
120
  if (sync)
117
- document.cookie = themeCookie(current.current);
121
+ writeThemeCookie(current.current);
118
122
  }, []);
119
123
  const value = useMemo(() => ({ theme: theme.mode, setTheme, colorTheme: theme.color, setColorTheme, syncTheme, setSyncTheme }), [theme, setTheme, setColorTheme, syncTheme, setSyncTheme]);
120
124
  return _jsx(Context.Provider, { value: value, children: children });
package/dist/theme.d.ts CHANGED
@@ -67,6 +67,14 @@ export declare function isColorTheme(value: unknown): value is ForgeColorTheme;
67
67
  export declare function parseThemeCookie(cookie: string): ForgeTheme | null;
68
68
  /** The `document.cookie` assignment that stores `theme` for every Forge app. */
69
69
  export declare function themeCookie(theme: ForgeTheme, domain?: string): string;
70
+ /**
71
+ * The `document.cookie` assignment that deletes a host-only theme cookie, or null where the theme cookie is host-only
72
+ * anyway (no shared domain). A host-only copy left over from before the shared domain was set sorts ahead of the
73
+ * shared cookie, so it would win every read and a new pick would never stick.
74
+ */
75
+ export declare function hostThemeCookieExpiry(domain?: string): string | null;
76
+ /** Writes the shared theme cookie, dropping any stale host-only copy first. */
77
+ export declare function writeThemeCookie(theme: ForgeTheme, domain?: string): void;
70
78
  /**
71
79
  * Inline `<head>` script that applies the theme before first paint: the shared
72
80
  * cookie when this app syncs, otherwise localStorage. Keep in step with
package/dist/theme.js CHANGED
@@ -53,6 +53,21 @@ export function themeCookie(theme, domain) {
53
53
  .filter(Boolean)
54
54
  .join('; ');
55
55
  }
56
+ /**
57
+ * The `document.cookie` assignment that deletes a host-only theme cookie, or null where the theme cookie is host-only
58
+ * anyway (no shared domain). A host-only copy left over from before the shared domain was set sorts ahead of the
59
+ * shared cookie, so it would win every read and a new pick would never stick.
60
+ */
61
+ export function hostThemeCookieExpiry(domain) {
62
+ return forgeCookieOptions(domain).domain ? `${THEME_COOKIE}=; Path=/; Max-Age=0` : null;
63
+ }
64
+ /** Writes the shared theme cookie, dropping any stale host-only copy first. */
65
+ export function writeThemeCookie(theme, domain) {
66
+ const expiry = hostThemeCookieExpiry(domain);
67
+ if (expiry)
68
+ document.cookie = expiry;
69
+ document.cookie = themeCookie(theme, domain);
70
+ }
56
71
  /**
57
72
  * Inline `<head>` script that applies the theme before first paint: the shared
58
73
  * cookie when this app syncs, otherwise localStorage. Keep in step with
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xforge-dev/forge-kit",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Shared auth, app registry and UI for xForge apps",
5
5
  "license": "MIT",
6
6
  "repository": {