@xforge-dev/forge-kit 0.17.0 → 0.18.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/dist/client.d.ts CHANGED
@@ -12,3 +12,4 @@ export { ForgeLogo, type ForgeLogoProps } from './forge-logo.js';
12
12
  export { ForgeSupportButton, BUY_ME_A_COFFEE_URL, BUY_ME_A_COFFEE_BUTTON, FORGE_SPONSOR_TIERS, ForgeSupporterBadge, type ForgeSupporterTier, type ForgeSupportButtonProps, } from './support-button.js';
13
13
  export { ForgeIgnInput, FORGE_ACCENTED_LETTERS, FORGE_NO_AUTOFILL, type ForgeIgnInputProps, } from './ign-input.js';
14
14
  export { ForgeFooter, type ForgeFooterProps } from './forge-footer.js';
15
+ export { ForgeJobsProvider } from './jobs-provider.js';
package/dist/client.js CHANGED
@@ -13,3 +13,4 @@ export { ForgeLogo } from './forge-logo.js';
13
13
  export { ForgeSupportButton, BUY_ME_A_COFFEE_URL, BUY_ME_A_COFFEE_BUTTON, FORGE_SPONSOR_TIERS, ForgeSupporterBadge, } from './support-button.js';
14
14
  export { ForgeIgnInput, FORGE_ACCENTED_LETTERS, FORGE_NO_AUTOFILL, } from './ign-input.js';
15
15
  export { ForgeFooter } from './forge-footer.js';
16
+ export { ForgeJobsProvider } from './jobs-provider.js';
@@ -62,7 +62,10 @@ function AccountPanel({ current, account, syncError, nav = [], accountDetails, g
62
62
  /** A nav group in the mobile panel: its name as a small heading, then its links, a section title before each run. */
63
63
  function PanelNavGroup({ group }) {
64
64
  const Icon = group.icon;
65
- return (_jsxs("div", { role: "group", "aria-label": group.label, className: "pt-2", children: [_jsxs("p", { className: "flex items-center gap-2 px-2 pb-1 text-xs font-medium text-muted-foreground", children: [Icon && _jsx(Icon, { "aria-hidden": true, className: "h-3.5 w-3.5" }), group.label] }), group.sections.map((section, i) => (_jsxs("div", { className: "space-y-1", children: [section.title && section.items.length > 0 && (_jsx("div", { className: "px-2 pb-0.5 pt-1.5 pl-9 text-xs text-muted-foreground", children: section.title })), section.items.map(({ href, label, icon, active }) => (_jsx(ForgePanelItem, { icon: icon, label: label, href: href, active: active }, href)))] }, section.key ?? i)))] }));
65
+ return (_jsxs("div", { role: "group", "aria-label": group.label, className: "pt-2", children: [_jsxs("p", { className: "flex items-center gap-2 px-2 pb-1 text-xs font-medium text-muted-foreground", children: [Icon && _jsx(Icon, { "aria-hidden": true, className: "h-3.5 w-3.5" }), group.label] }), group.sections.map((section, i) => (_jsxs("div", { className: "space-y-1", children: [section.title && section.items.length > 0 && (
66
+ // A text title sits over the links' labels; a rich one (an avatar and name) brings its own leading
67
+ // media, so it lines up with their icons instead.
68
+ _jsx("div", { className: `px-2 pb-0.5 pt-1.5 text-xs text-muted-foreground ${typeof section.title === 'string' ? 'pl-9' : ''}`, children: section.title })), section.items.map(({ href, label, icon, active }) => (_jsx(ForgePanelItem, { icon: icon, label: label, href: href, active: active }, href)))] }, section.key ?? i)))] }));
66
69
  }
67
70
  /** Discord's mark in `currentColor`; give it Discord's blurple (`text-[#5865F2]`) next to a Discord name. */
68
71
  export function DiscordIcon({ className }) {
package/dist/index.d.ts CHANGED
@@ -7,3 +7,4 @@ export { isForgeAuthConfigured } from './config.js';
7
7
  export * from './theme.js';
8
8
  export { FORGE_BRANDS, FORGE_CDN, type ForgeBrand, type ForgeBrandId } from './brand.js';
9
9
  export { HANDOFF_PATH, LEGACY_ORIGINS, LEGACY_ROOT_DOMAIN, decideLegacy, legacyReceiveHtml, legacySendHtml, type LegacyDecision } from './legacy.js';
10
+ export * from './jobs.js';
package/dist/index.js CHANGED
@@ -7,3 +7,4 @@ export { isForgeAuthConfigured } from './config.js';
7
7
  export * from './theme.js';
8
8
  export { FORGE_BRANDS, FORGE_CDN } from './brand.js';
9
9
  export { HANDOFF_PATH, LEGACY_ORIGINS, LEGACY_ROOT_DOMAIN, decideLegacy, legacyReceiveHtml, legacySendHtml } from './legacy.js';
10
+ export * from './jobs.js';
@@ -0,0 +1,7 @@
1
+ import type { ReactElement, ReactNode } from 'react';
2
+ import { type JobCatalog } from './jobs.js';
3
+ /** Installs the server-fetched catalog before the children render, so client lookups agree with the server. */
4
+ export declare function ForgeJobsProvider({ catalog, children }: {
5
+ catalog: JobCatalog;
6
+ children: ReactNode;
7
+ }): ReactElement;
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
+ import { getJobCatalog, setJobCatalog } from './jobs.js';
4
+ /** Installs the server-fetched catalog before the children render, so client lookups agree with the server. */
5
+ export function ForgeJobsProvider({ catalog, children }) {
6
+ if (catalog.updated !== getJobCatalog().updated)
7
+ setJobCatalog(catalog);
8
+ return _jsx(_Fragment, { children: children });
9
+ }
@@ -0,0 +1,10 @@
1
+ import { type JobCatalog } from './jobs.js';
2
+ /**
3
+ * Fetches the shared job catalog (Next's fetch cache, one hour by default), validates it and installs it
4
+ * as the registry. Any failure leaves the current catalog in place and warns once per distinct error.
5
+ */
6
+ export declare function refreshJobCatalog(opts?: {
7
+ url?: string;
8
+ revalidate?: number;
9
+ fetch?: typeof fetch;
10
+ }): Promise<JobCatalog>;
@@ -0,0 +1,25 @@
1
+ import { getJobCatalog, parseJobCatalog, setJobCatalog, JOB_CATALOG_URL } from './jobs.js';
2
+ const warned = new Set();
3
+ /**
4
+ * Fetches the shared job catalog (Next's fetch cache, one hour by default), validates it and installs it
5
+ * as the registry. Any failure leaves the current catalog in place and warns once per distinct error.
6
+ */
7
+ export async function refreshJobCatalog(opts = {}) {
8
+ const doFetch = opts.fetch ?? fetch;
9
+ try {
10
+ const res = await doFetch(opts.url ?? JOB_CATALOG_URL, { next: { revalidate: opts.revalidate ?? 3600 } });
11
+ if (!res.ok)
12
+ throw new Error(`job catalog: HTTP ${res.status}`);
13
+ const next = parseJobCatalog(await res.json());
14
+ setJobCatalog(next);
15
+ return next;
16
+ }
17
+ catch (e) {
18
+ const message = e instanceof Error ? e.message : String(e);
19
+ if (!warned.has(message)) {
20
+ warned.add(message);
21
+ console.warn(`[forge-kit] job catalog refresh failed: ${message}`);
22
+ }
23
+ return getJobCatalog();
24
+ }
25
+ }
@@ -0,0 +1,2 @@
1
+ import type { JobCatalog } from './jobs.js';
2
+ export declare const JOBS_SNAPSHOT: JobCatalog;