@jini-ai/admin 0.4.8 → 0.4.10
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 +8 -0
- package/dist/forms/html-rules.js +1 -0
- package/dist/seo/models.d.ts +5 -6
- package/dist/seo/react/components/SitemapModal.d.ts +4 -6
- package/dist/seo/react/components/SitemapModal.js +1 -1
- package/dist/seo/react/hooks/SitemapModal.hooks.d.ts +7 -4
- package/dist/seo/react/hooks/SitemapModal.hooks.js +7 -4
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.10 — 2026-10-13
|
|
4
|
+
|
|
5
|
+
- Forms HTML starter: URL fields emit `type="text"` plus the registry's URL hints (`inputmode`, `autocomplete`, `spellcheck`, `autocapitalize`), so bare domains such as `tovu.dev` are no longer refused by the browser. CMS peer floor ^0.5.11.
|
|
6
|
+
|
|
7
|
+
## 0.4.9 — 2026-10-13
|
|
8
|
+
|
|
9
|
+
- Sitemap modal: Regenerate no longer reads `/sitemap.xml` twice. The regenerate mutation already invalidates the cached sitemap read (since 1c5d476f), so the modal's extra refetch is gone; the modal still shows the fresh XML after a successful regenerate and keeps the old XML after a failed one.
|
|
10
|
+
|
|
3
11
|
## 0.4.8 — 2026-10-13
|
|
4
12
|
|
|
5
13
|
- Share-image warning checks decoded size against 1200×630 (width and height independently; was width ≥ 600). New copy key: `The share image is only {height} px tall; use an image at least 630 px tall.`; the width key now says 1200 px.
|
package/dist/forms/html-rules.js
CHANGED
|
@@ -84,6 +84,7 @@ function starterAttributes(field, kind) {
|
|
|
84
84
|
const constraints = [
|
|
85
85
|
["placeholder", kind.control === "select" ? undefined : field.placeholder], ["minlength", field.minLength], ["maxlength", field.maxLength],
|
|
86
86
|
["pattern", field.pattern], ["min", field.min], ["max", field.max], ["step", field.step], ["accept", field.accept?.join(",")],
|
|
87
|
+
...Object.entries(kind.attributes ?? {}),
|
|
87
88
|
];
|
|
88
89
|
return `name="${escapeHtml(field.id)}"${field.required ? " required" : ""}` +
|
|
89
90
|
constraints.filter(([, value]) => value != null && value !== "").map(([name, value]) => ` ${name}="${escapeHtml(String(value))}"`).join("");
|
package/dist/seo/models.d.ts
CHANGED
|
@@ -57,9 +57,9 @@ export interface SeoController {
|
|
|
57
57
|
defaultOgImage: string;
|
|
58
58
|
setDefaultOgImage: (value: string) => void;
|
|
59
59
|
/** Resolves `true` on success, `false` on a caught failure (`error` is set either way this
|
|
60
|
-
* already did)
|
|
61
|
-
*
|
|
62
|
-
*
|
|
60
|
+
* already did). Success invalidates the cached `/sitemap.xml` read, so `SitemapModal.tsx`'s
|
|
61
|
+
* footer Regenerate button shows fresh XML without its own refetch; a failed attempt leaves
|
|
62
|
+
* the viewed XML alone. The pre-existing caller, `react/pages/SeoPage.tsx`'s own Regenerate button, still just fires this as
|
|
63
63
|
* a plain `onClick` and discards the return value — this is a widening, not a breaking change. */
|
|
64
64
|
regenerateSitemap: () => Promise<boolean>;
|
|
65
65
|
/** Whether `SitemapModal.tsx` ("View sitemap") is open. `react/pages/SeoPage.tsx` stays markup-only (this file's
|
|
@@ -136,9 +136,8 @@ export interface SitemapModalController {
|
|
|
136
136
|
setFilter: (value: string) => void;
|
|
137
137
|
view: SitemapModalView;
|
|
138
138
|
setView: (view: SitemapModalView) => void;
|
|
139
|
-
/** Re-runs the fetch
|
|
140
|
-
*
|
|
141
|
-
* without the operator closing and reopening the modal. */
|
|
139
|
+
/** Re-runs the fetch. Retained for the hook ABI; after a successful regenerate the mutation's
|
|
140
|
+
* cache invalidation already refreshes the count/table/raw view, so the modal no longer calls it. */
|
|
142
141
|
refetch: () => void;
|
|
143
142
|
}
|
|
144
143
|
export interface MediaRefFieldController {
|
|
@@ -12,9 +12,8 @@ import { useWiredSitemapModal } from "../hooks/use-sitemap-modal.hooks.js";
|
|
|
12
12
|
* single scrolling region between fixed header and footer.
|
|
13
13
|
*
|
|
14
14
|
* Domain state (fetch, parse, filter, view toggle) lives in `hooks/use-sitemap-modal
|
|
15
|
-
* .hooks.ts`; this file is markup only
|
|
16
|
-
*
|
|
17
|
-
* colocated `react/hooks/SitemapModal.hooks.ts`, see that file's header for why it isn't folded into either.
|
|
15
|
+
* .hooks.ts`; this file is markup only. The outer `useSeo()` mutation owns regeneration and
|
|
16
|
+
* cache invalidation; `react/hooks/SitemapModal.hooks.ts` forwards that action without another read.
|
|
18
17
|
*
|
|
19
18
|
* ## Agent handles
|
|
20
19
|
* Every interactive element carries its own `agentHandle` (grep `agentHandle(` in `react/pages/SeoPage.tsx` for
|
|
@@ -34,9 +33,8 @@ export interface SitemapModalProps {
|
|
|
34
33
|
/** `saving` from `useSeo()` — shared with the outer page's own Save/Regenerate buttons, same as
|
|
35
34
|
* today's single-flag convention (`react/pages/SeoPage.tsx`'s existing `disabled={saving}` on both). */
|
|
36
35
|
regenerating: boolean;
|
|
37
|
-
/** `regenerateSitemap` from `useSeo()`.
|
|
38
|
-
*
|
|
39
|
-
* regenerate it refetches"). */
|
|
36
|
+
/** `regenerateSitemap` from `useSeo()`. Its mutation invalidates the sitemap cache on
|
|
37
|
+
* success; a caught failure returns `false` and leaves the viewed XML alone. */
|
|
40
38
|
onRegenerate: () => Promise<boolean>;
|
|
41
39
|
onClose: () => void;
|
|
42
40
|
/** Injectable seam for the modal's fetch/parse/filter/view state. Defaults to the real
|
|
@@ -62,7 +62,7 @@ export function SitemapModal({ locale, sitemapEnabled, regenerating, onRegenerat
|
|
|
62
62
|
const t = useSeoCopy();
|
|
63
63
|
const modal = useModal({ enabled: sitemapEnabled, onClose });
|
|
64
64
|
const { title } = useSitemapPresentation({ locale, modal });
|
|
65
|
-
const { handleRegenerate } = useSitemapModalRegenerate({ onRegenerate
|
|
65
|
+
const { handleRegenerate } = useSitemapModalRegenerate({ onRegenerate });
|
|
66
66
|
// Native modality keeps Tab from reaching the background, as MediaPickerDialog now does too.
|
|
67
67
|
return (_jsxs(Dialog, { open: true, title: title, onClose: () => onClose(), className: "settings-dialog tovu-domain-dialog sitemap-modal", children: [_jsx("div", { className: "sitemap-modal-header", children: _jsx(SitemapModalHeaderActions, { locale: locale, modal: modal }) }), _jsx("div", { className: "sitemap-modal-body", children: _jsx(SitemapModalBody, { locale: locale, sitemapEnabled: sitemapEnabled, modal: modal }) }), _jsx("div", { className: "widget-picker-footer", children: _jsxs("span", { className: "editor-actions", children: [_jsx("button", { type: "button", className: "btn-secondary", onClick: handleRegenerate, disabled: regenerating, ...agentHandle({ handle: "seo-sitemap-modal-regenerate" }, {
|
|
68
68
|
role: "button",
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { SitemapModalController } from '../../models.js';
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/** The regeneration mutation owns cache invalidation; forwarding it must not start a second
|
|
3
|
+
* XML read. Failed writes leave the viewed XML alone.
|
|
4
|
+
* @returns The mutation callback as the modal's click handler; no additional I/O.
|
|
5
|
+
* @complexity O(1).
|
|
6
|
+
*/
|
|
7
|
+
export declare function useSitemapModalRegenerate({ onRegenerate }: {
|
|
4
8
|
onRegenerate: () => Promise<boolean>;
|
|
5
|
-
refetch: () => void;
|
|
6
9
|
}, _optional?: Record<string, never>): {
|
|
7
|
-
handleRegenerate: () => Promise<
|
|
10
|
+
handleRegenerate: () => Promise<boolean>;
|
|
8
11
|
};
|
|
9
12
|
export declare function useSitemapTable({ modal }: {
|
|
10
13
|
modal: SitemapModalController;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { useSeoCopy, useSeoOptions } from './SeoPorts.hooks.js';
|
|
2
2
|
import { buildAgentListHandles } from '@jini-ai/agentic';
|
|
3
|
-
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
/** The regeneration mutation owns cache invalidation; forwarding it must not start a second
|
|
4
|
+
* XML read. Failed writes leave the viewed XML alone.
|
|
5
|
+
* @returns The mutation callback as the modal's click handler; no additional I/O.
|
|
6
|
+
* @complexity O(1).
|
|
7
|
+
*/
|
|
8
|
+
export function useSitemapModalRegenerate({ onRegenerate }, _optional = {}) {
|
|
9
|
+
return { handleRegenerate: onRegenerate };
|
|
7
10
|
}
|
|
8
11
|
export function useSitemapTable({ modal }, _optional = {}) {
|
|
9
12
|
return { rowHandles: buildAgentListHandles({ prefix: 'seo-sitemap-row', ids: modal.filteredEntries.map(entry => entry.loc) }) };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/admin",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.10",
|
|
4
4
|
"description": "Composable admin surface for Jini-hosted products: framework-free contracts, panel registry, and route model in `/core`; React shell and panels in `/react`. Import only the layers you need.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -437,7 +437,7 @@
|
|
|
437
437
|
"@jini-ai/ui": "^0.5.1",
|
|
438
438
|
"@jini-ai/ui-kit": "^0.1.3",
|
|
439
439
|
"@jini-ai/agent-plugins": "^0.4.3",
|
|
440
|
-
"@jini-ai/cms": "^0.5.
|
|
440
|
+
"@jini-ai/cms": "^0.5.11",
|
|
441
441
|
"@jini-ai/core": "^0.4.3"
|
|
442
442
|
},
|
|
443
443
|
"peerDependenciesMeta": {
|
|
@@ -476,12 +476,12 @@
|
|
|
476
476
|
"react": "^19.2.0",
|
|
477
477
|
"react-dom": "^19.2.0",
|
|
478
478
|
"@testing-library/user-event": "^14.6.1",
|
|
479
|
-
"@jini-ai/
|
|
480
|
-
"@jini-ai/agent-plugins": "^0.4.6",
|
|
479
|
+
"@jini-ai/cms": "^0.5.11",
|
|
481
480
|
"@jini-ai/ui-kit": "^0.1.4",
|
|
482
|
-
"@jini-ai/
|
|
481
|
+
"@jini-ai/core": "^0.4.5",
|
|
483
482
|
"@jini-ai/ui": "^0.5.1",
|
|
484
|
-
"@jini-ai/
|
|
483
|
+
"@jini-ai/agentic": "^0.4.4",
|
|
484
|
+
"@jini-ai/agent-plugins": "^0.4.6"
|
|
485
485
|
},
|
|
486
486
|
"typesVersions": {
|
|
487
487
|
"*": {
|