@jini-ai/admin 0.4.3 → 0.4.5
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 +4 -0
- package/dist/comments/comments.module.d.ts +4 -4
- package/dist/comments/messages.en.d.ts +4 -4
- package/dist/comments/messages.en.js +4 -4
- package/dist/comments/react/components/QueueSection.js +1 -1
- package/dist/comments/react/index.d.ts +16 -16
- package/dist/forms/forms.module.d.ts +3 -2
- package/dist/forms/html-rules.d.ts +14 -0
- package/dist/forms/html-rules.js +10 -0
- package/dist/forms/messages.en.d.ts +3 -2
- package/dist/forms/messages.en.js +4 -3
- package/dist/forms/react/components/FormEditorHeaderText.js +2 -2
- package/dist/forms/react/components/FormSubmissionDetail.d.ts +3 -1
- package/dist/forms/react/components/FormSubmissionDetail.js +3 -2
- package/dist/forms/react/components/FormSubmissions.js +1 -1
- package/dist/forms/react/hooks/forms-view.hooks.d.ts +1 -6
- package/dist/forms/react/hooks/forms-view.hooks.js +3 -4
- package/dist/forms/react/index.d.ts +9 -6
- package/dist/forms/react/index.js +3 -1
- package/dist/forms/react/pages/FormsList.js +2 -7
- package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts +3 -1
- package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js +5 -1
- package/dist/react/components/ConfirmDialog/use-confirm-request.d.ts +22 -0
- package/dist/react/components/ConfirmDialog/use-confirm-request.js +53 -0
- package/dist/react/components/RowMenu/RowMenu.hooks.js +14 -3
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +1 -0
- package/dist/redirects/messages.en.d.ts +9 -7
- package/dist/redirects/messages.en.js +14 -9
- package/dist/redirects/react/hooks/RedirectsPage.hooks.js +2 -2
- package/dist/redirects/react/index.d.ts +36 -28
- package/dist/redirects/react/pages/RedirectsPage.js +1 -1
- package/dist/redirects/redirects.module.d.ts +9 -7
- package/dist/seo/messages.en.d.ts +5 -4
- package/dist/seo/messages.en.js +6 -5
- package/dist/seo/react/components/MediaRefField.d.ts +4 -0
- package/dist/seo/react/components/MediaRefField.js +2 -2
- package/dist/seo/react/components/SitemapModal.js +4 -2
- package/dist/seo/react/hooks/MediaRefField.hooks.d.ts +4 -1
- package/dist/seo/react/hooks/MediaRefField.hooks.js +3 -3
- package/dist/seo/react/index.d.ts +15 -12
- package/dist/seo/react/options.d.ts +7 -0
- package/dist/seo/react/pages/SeoPage.js +23 -23
- package/dist/seo/rules.d.ts +6 -0
- package/dist/seo/rules.js +8 -0
- package/dist/seo/seo.module.d.ts +5 -4
- package/dist/widgets/react/pages/WidgetRegionEditor.js +1 -1
- package/package.json +6 -6
|
@@ -12,13 +12,14 @@ const VIEWPORT_MARGIN = 8;
|
|
|
12
12
|
* visible jump. Recomputed on scroll and resize too: a portaled menu is a DOM sibling of its anchor,
|
|
13
13
|
* not a child, so it does not track the anchor's position on its own the way an in-flow popup would.
|
|
14
14
|
*
|
|
15
|
-
* Click-outside
|
|
15
|
+
* Click-outside and Escape close. Escape is document-scoped so it also works after focus
|
|
16
|
+
* moves away from the popup. Scoped to the open window only, same lifecycle discipline as
|
|
16
17
|
* `ConfirmButton`'s armed-only document listeners — a closed, idle `RowMenu` costs nothing beyond
|
|
17
18
|
* its trigger button even with many mounted per table.
|
|
18
19
|
*
|
|
19
20
|
* @complexity O(1) per call and per scroll/resize/mousedown event.
|
|
20
21
|
*/
|
|
21
|
-
function trackOpenMenu({ trigger, menu }, { window, document, onPosition, onDismiss }) {
|
|
22
|
+
function trackOpenMenu({ trigger, menu }, { window, document, onPosition, onDismiss, onEscape }) {
|
|
22
23
|
function reposition() {
|
|
23
24
|
const rect = trigger.getBoundingClientRect();
|
|
24
25
|
const menuHeight = menu.offsetHeight;
|
|
@@ -41,14 +42,23 @@ function trackOpenMenu({ trigger, menu }, { window, document, onPosition, onDism
|
|
|
41
42
|
return;
|
|
42
43
|
onDismiss();
|
|
43
44
|
}
|
|
45
|
+
function onDocKeyDown(e) {
|
|
46
|
+
if (e.key !== 'Escape' || e.defaultPrevented)
|
|
47
|
+
return;
|
|
48
|
+
e.preventDefault();
|
|
49
|
+
e.stopPropagation();
|
|
50
|
+
onEscape();
|
|
51
|
+
}
|
|
44
52
|
reposition();
|
|
45
53
|
window.addEventListener('scroll', reposition, true);
|
|
46
54
|
window.addEventListener('resize', reposition);
|
|
47
55
|
document.addEventListener('mousedown', onDocMouseDown);
|
|
56
|
+
document.addEventListener('keydown', onDocKeyDown);
|
|
48
57
|
return () => {
|
|
49
58
|
window.removeEventListener('scroll', reposition, true);
|
|
50
59
|
window.removeEventListener('resize', reposition);
|
|
51
60
|
document.removeEventListener('mousedown', onDocMouseDown);
|
|
61
|
+
document.removeEventListener('keydown', onDocKeyDown);
|
|
52
62
|
};
|
|
53
63
|
}
|
|
54
64
|
/**
|
|
@@ -89,7 +99,7 @@ export function useRowMenu({ itemCount, window, document }) {
|
|
|
89
99
|
let stop;
|
|
90
100
|
return (menu) => {
|
|
91
101
|
if (menu)
|
|
92
|
-
stop = trackOpenMenu({ trigger: anchor, menu }, { window, document, onPosition: setPosition, onDismiss: () => close(false) });
|
|
102
|
+
stop = trackOpenMenu({ trigger: anchor, menu }, { window, document, onPosition: setPosition, onDismiss: () => close(false), onEscape: () => close(true) });
|
|
93
103
|
else
|
|
94
104
|
stop();
|
|
95
105
|
};
|
|
@@ -140,6 +150,7 @@ export function useRowMenu({ itemCount, window, document }) {
|
|
|
140
150
|
break;
|
|
141
151
|
case 'Escape':
|
|
142
152
|
e.preventDefault();
|
|
153
|
+
e.stopPropagation();
|
|
143
154
|
close(true);
|
|
144
155
|
break;
|
|
145
156
|
case 'Tab':
|
package/dist/react/index.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export { ConfirmButton } from './components/ConfirmButton/ConfirmButton.js';
|
|
|
37
37
|
export type { ConfirmButtonProps } from './components/ConfirmButton/ConfirmButton.js';
|
|
38
38
|
export { ConfirmDialog } from './components/ConfirmDialog/ConfirmDialog.js';
|
|
39
39
|
export type { ConfirmDialogProps } from './components/ConfirmDialog/ConfirmDialog.js';
|
|
40
|
+
export { useConfirmRequest } from './components/ConfirmDialog/use-confirm-request.js';
|
|
41
|
+
export type { ConfirmRequestController, ConfirmRequestPresentation } from './components/ConfirmDialog/use-confirm-request.js';
|
|
40
42
|
export type { ConfirmDialogController, UseConfirmDialog } from './components/ConfirmDialog/ConfirmDialog.hooks.js';
|
|
41
43
|
export { ConfirmDialogDefaultsProvider } from './components/ConfirmDialog/ConfirmDialog.hooks.js';
|
|
42
44
|
export type { ConfirmDialogDefaults, ConfirmDialogDefaultsProviderProps, } from './components/ConfirmDialog/ConfirmDialog.hooks.js';
|
package/dist/react/index.js
CHANGED
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
export { resolveTone, toneClassName } from './types.js';
|
|
37
37
|
export { ConfirmButton } from './components/ConfirmButton/ConfirmButton.js';
|
|
38
38
|
export { ConfirmDialog } from './components/ConfirmDialog/ConfirmDialog.js';
|
|
39
|
+
export { useConfirmRequest } from './components/ConfirmDialog/use-confirm-request.js';
|
|
39
40
|
// Host-wide `ConfirmDialog` defaults (today just a translated `cancelLabel`), set once at an app
|
|
40
41
|
// root rather than passed at every call site — see `ConfirmDialogDefaultsProvider`'s doc comment.
|
|
41
42
|
export { ConfirmDialogDefaultsProvider } from './components/ConfirmDialog/ConfirmDialog.hooks.js';
|
|
@@ -9,8 +9,7 @@ export declare const redirectsMessagesEn: {
|
|
|
9
9
|
readonly Import: "Import";
|
|
10
10
|
readonly Marketing: "Marketing";
|
|
11
11
|
readonly Redirects: "Redirects";
|
|
12
|
-
readonly "
|
|
13
|
-
readonly ") also show up here.": ") also show up here.";
|
|
12
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
14
13
|
readonly "Match type": "Match type";
|
|
15
14
|
readonly "From path": "From path";
|
|
16
15
|
readonly "To target": "To target";
|
|
@@ -31,9 +30,9 @@ export declare const redirectsMessagesEn: {
|
|
|
31
30
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
32
31
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
33
32
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
34
|
-
readonly exact: "
|
|
35
|
-
readonly prefix: "
|
|
36
|
-
readonly wildcard: "
|
|
33
|
+
readonly exact: "Exact match";
|
|
34
|
+
readonly prefix: "Starts with";
|
|
35
|
+
readonly wildcard: "Wildcard";
|
|
37
36
|
readonly Status: "Status";
|
|
38
37
|
readonly More: "More";
|
|
39
38
|
readonly Delete: "Delete";
|
|
@@ -41,8 +40,8 @@ export declare const redirectsMessagesEn: {
|
|
|
41
40
|
readonly Enable: "Enable";
|
|
42
41
|
readonly "Saving\u2026": "Saving…";
|
|
43
42
|
readonly Created: "Created";
|
|
44
|
-
readonly active: "
|
|
45
|
-
readonly disabled: "
|
|
43
|
+
readonly active: "Active";
|
|
44
|
+
readonly disabled: "Disabled";
|
|
46
45
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
47
46
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
48
47
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -50,6 +49,9 @@ export declare const redirectsMessagesEn: {
|
|
|
50
49
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
51
50
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
52
51
|
readonly "\"?": "\"?";
|
|
52
|
+
readonly manual: "Manual";
|
|
53
|
+
readonly auto_slug_change: "URL change";
|
|
54
|
+
readonly import: "Imported";
|
|
53
55
|
};
|
|
54
56
|
/** English fallback with the same named-placeholder interpolation as the host dictionary. */
|
|
55
57
|
export declare const translateRedirectsEn: RedirectsTranslate;
|
|
@@ -8,8 +8,7 @@ export const redirectsMessagesEn = {
|
|
|
8
8
|
"Import": "Import",
|
|
9
9
|
"Marketing": "Marketing",
|
|
10
10
|
"Redirects": "Redirects",
|
|
11
|
-
"
|
|
12
|
-
") also show up here.": ") also show up here.",
|
|
11
|
+
"Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.",
|
|
13
12
|
"Match type": "Match type",
|
|
14
13
|
"From path": "From path",
|
|
15
14
|
"To target": "To target",
|
|
@@ -30,9 +29,9 @@ export const redirectsMessagesEn = {
|
|
|
30
29
|
"Loading redirects…": "Loading redirects…",
|
|
31
30
|
"Not valid JSON.": "Not valid JSON.",
|
|
32
31
|
"Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.",
|
|
33
|
-
"exact": "
|
|
34
|
-
"prefix": "
|
|
35
|
-
"wildcard": "
|
|
32
|
+
"exact": "Exact match",
|
|
33
|
+
"prefix": "Starts with",
|
|
34
|
+
"wildcard": "Wildcard",
|
|
36
35
|
"Status": "Status",
|
|
37
36
|
"More": "More",
|
|
38
37
|
"Delete": "Delete",
|
|
@@ -40,16 +39,22 @@ export const redirectsMessagesEn = {
|
|
|
40
39
|
"Enable": "Enable",
|
|
41
40
|
"Saving…": "Saving…",
|
|
42
41
|
"Created": "Created",
|
|
43
|
-
"active": "
|
|
44
|
-
"disabled": "
|
|
42
|
+
"active": "Active",
|
|
43
|
+
"disabled": "Disabled",
|
|
45
44
|
"{created} created, {failed} failed.": "{created} created, {failed} failed.",
|
|
46
45
|
"Item {index} ({code})": "Item {index} ({code})",
|
|
47
46
|
"Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"",
|
|
48
47
|
"Paste a JSON array of ": "Paste a JSON array of ",
|
|
49
48
|
" rule objects (1-500 items)": " rule objects (1-500 items)",
|
|
50
49
|
"Delete the redirect rule from \"": "Delete the redirect rule from \"",
|
|
51
|
-
"\"?": "\"?"
|
|
50
|
+
"\"?": "\"?",
|
|
51
|
+
"manual": "Manual",
|
|
52
|
+
"auto_slug_change": "URL change",
|
|
53
|
+
"import": "Imported",
|
|
52
54
|
};
|
|
53
55
|
/** English fallback with the same named-placeholder interpolation as the host dictionary. */
|
|
54
|
-
export const translateRedirectsEn = (key, vars = {}) =>
|
|
56
|
+
export const translateRedirectsEn = (key, vars = {}) => {
|
|
57
|
+
const template = Object.hasOwn(redirectsMessagesEn, key) ? redirectsMessagesEn[key] : key;
|
|
58
|
+
return template.replace(/\{(\w+)\}/g, (match, name) => String(vars[name] ?? match));
|
|
59
|
+
};
|
|
55
60
|
//# sourceMappingURL=messages.en.js.map
|
|
@@ -12,9 +12,9 @@ export function useRedirectsPage({ useRedirectsHook = useWiredRedirects }, _opti
|
|
|
12
12
|
const columns = [
|
|
13
13
|
{ key: 'from', header: t('From'), cell: (rule) => rule.fromPattern },
|
|
14
14
|
{ key: 'to', header: t('To'), cell: (rule) => rule.toTarget },
|
|
15
|
-
{ key: 'type', header: t('Type'), cell: (rule) => rule.matchType },
|
|
15
|
+
{ key: 'type', header: t('Type'), cell: (rule) => t(rule.matchType, { serverLabel: rule.matchType }) },
|
|
16
16
|
{ key: 'code', header: t('Code'), cell: (rule) => rule.statusCode },
|
|
17
|
-
{ key: 'source', header: t('Source'), cell: (rule) => rule.source },
|
|
17
|
+
{ key: 'source', header: t('Source'), cell: (rule) => t(rule.source, { serverLabel: rule.source }) },
|
|
18
18
|
// The host's shared serverLabel owns enum localization, including unknown-value passthrough.
|
|
19
19
|
{ key: 'status', header: t('Status'), cell: (rule) => createElement('span', { className: `status status-${rule.status}` }, t(rule.status, { serverLabel: rule.status })) },
|
|
20
20
|
{ key: 'hits', header: t('Hits'), cell: (rule, index) => createElement(HitCountCell, { t, redirectId: rule.id, ...(rowMenuHandles[index] ? { agentHandleBase: rowMenuHandles[index] } : {}) }) },
|
|
@@ -24,8 +24,7 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
24
24
|
readonly Import: "Import";
|
|
25
25
|
readonly Marketing: "Marketing";
|
|
26
26
|
readonly Redirects: "Redirects";
|
|
27
|
-
readonly "
|
|
28
|
-
readonly ") also show up here.": ") also show up here.";
|
|
27
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
29
28
|
readonly "Match type": "Match type";
|
|
30
29
|
readonly "From path": "From path";
|
|
31
30
|
readonly "To target": "To target";
|
|
@@ -46,9 +45,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
46
45
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
47
46
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
48
47
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
49
|
-
readonly exact: "
|
|
50
|
-
readonly prefix: "
|
|
51
|
-
readonly wildcard: "
|
|
48
|
+
readonly exact: "Exact match";
|
|
49
|
+
readonly prefix: "Starts with";
|
|
50
|
+
readonly wildcard: "Wildcard";
|
|
52
51
|
readonly Status: "Status";
|
|
53
52
|
readonly More: "More";
|
|
54
53
|
readonly Delete: "Delete";
|
|
@@ -56,8 +55,8 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
56
55
|
readonly Enable: "Enable";
|
|
57
56
|
readonly "Saving\u2026": "Saving…";
|
|
58
57
|
readonly Created: "Created";
|
|
59
|
-
readonly active: "
|
|
60
|
-
readonly disabled: "
|
|
58
|
+
readonly active: "Active";
|
|
59
|
+
readonly disabled: "Disabled";
|
|
61
60
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
62
61
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
63
62
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -65,6 +64,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
65
64
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
66
65
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
67
66
|
readonly "\"?": "\"?";
|
|
67
|
+
readonly manual: "Manual";
|
|
68
|
+
readonly auto_slug_change: "URL change";
|
|
69
|
+
readonly import: "Imported";
|
|
68
70
|
};
|
|
69
71
|
pages: {
|
|
70
72
|
readonly list: {
|
|
@@ -101,8 +103,7 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
101
103
|
readonly Import: "Import";
|
|
102
104
|
readonly Marketing: "Marketing";
|
|
103
105
|
readonly Redirects: "Redirects";
|
|
104
|
-
readonly "
|
|
105
|
-
readonly ") also show up here.": ") also show up here.";
|
|
106
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
106
107
|
readonly "Match type": "Match type";
|
|
107
108
|
readonly "From path": "From path";
|
|
108
109
|
readonly "To target": "To target";
|
|
@@ -123,9 +124,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
123
124
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
124
125
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
125
126
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
126
|
-
readonly exact: "
|
|
127
|
-
readonly prefix: "
|
|
128
|
-
readonly wildcard: "
|
|
127
|
+
readonly exact: "Exact match";
|
|
128
|
+
readonly prefix: "Starts with";
|
|
129
|
+
readonly wildcard: "Wildcard";
|
|
129
130
|
readonly Status: "Status";
|
|
130
131
|
readonly More: "More";
|
|
131
132
|
readonly Delete: "Delete";
|
|
@@ -133,8 +134,8 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
133
134
|
readonly Enable: "Enable";
|
|
134
135
|
readonly "Saving\u2026": "Saving…";
|
|
135
136
|
readonly Created: "Created";
|
|
136
|
-
readonly active: "
|
|
137
|
-
readonly disabled: "
|
|
137
|
+
readonly active: "Active";
|
|
138
|
+
readonly disabled: "Disabled";
|
|
138
139
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
139
140
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
140
141
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -142,6 +143,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
142
143
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
143
144
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
144
145
|
readonly "\"?": "\"?";
|
|
146
|
+
readonly manual: "Manual";
|
|
147
|
+
readonly auto_slug_change: "URL change";
|
|
148
|
+
readonly import: "Imported";
|
|
145
149
|
};
|
|
146
150
|
readonly pages: {
|
|
147
151
|
readonly list: {
|
|
@@ -176,8 +180,7 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
176
180
|
readonly Import: "Import";
|
|
177
181
|
readonly Marketing: "Marketing";
|
|
178
182
|
readonly Redirects: "Redirects";
|
|
179
|
-
readonly "
|
|
180
|
-
readonly ") also show up here.": ") also show up here.";
|
|
183
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
181
184
|
readonly "Match type": "Match type";
|
|
182
185
|
readonly "From path": "From path";
|
|
183
186
|
readonly "To target": "To target";
|
|
@@ -198,9 +201,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
198
201
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
199
202
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
200
203
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
201
|
-
readonly exact: "
|
|
202
|
-
readonly prefix: "
|
|
203
|
-
readonly wildcard: "
|
|
204
|
+
readonly exact: "Exact match";
|
|
205
|
+
readonly prefix: "Starts with";
|
|
206
|
+
readonly wildcard: "Wildcard";
|
|
204
207
|
readonly Status: "Status";
|
|
205
208
|
readonly More: "More";
|
|
206
209
|
readonly Delete: "Delete";
|
|
@@ -208,8 +211,8 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
208
211
|
readonly Enable: "Enable";
|
|
209
212
|
readonly "Saving\u2026": "Saving…";
|
|
210
213
|
readonly Created: "Created";
|
|
211
|
-
readonly active: "
|
|
212
|
-
readonly disabled: "
|
|
214
|
+
readonly active: "Active";
|
|
215
|
+
readonly disabled: "Disabled";
|
|
213
216
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
214
217
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
215
218
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -217,6 +220,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
217
220
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
218
221
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
219
222
|
readonly "\"?": "\"?";
|
|
223
|
+
readonly manual: "Manual";
|
|
224
|
+
readonly auto_slug_change: "URL change";
|
|
225
|
+
readonly import: "Imported";
|
|
220
226
|
};
|
|
221
227
|
readonly pages: {
|
|
222
228
|
readonly list: {
|
|
@@ -255,8 +261,7 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
255
261
|
readonly Import: "Import";
|
|
256
262
|
readonly Marketing: "Marketing";
|
|
257
263
|
readonly Redirects: "Redirects";
|
|
258
|
-
readonly "
|
|
259
|
-
readonly ") also show up here.": ") also show up here.";
|
|
264
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
260
265
|
readonly "Match type": "Match type";
|
|
261
266
|
readonly "From path": "From path";
|
|
262
267
|
readonly "To target": "To target";
|
|
@@ -277,9 +282,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
277
282
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
278
283
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
279
284
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
280
|
-
readonly exact: "
|
|
281
|
-
readonly prefix: "
|
|
282
|
-
readonly wildcard: "
|
|
285
|
+
readonly exact: "Exact match";
|
|
286
|
+
readonly prefix: "Starts with";
|
|
287
|
+
readonly wildcard: "Wildcard";
|
|
283
288
|
readonly Status: "Status";
|
|
284
289
|
readonly More: "More";
|
|
285
290
|
readonly Delete: "Delete";
|
|
@@ -287,8 +292,8 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
287
292
|
readonly Enable: "Enable";
|
|
288
293
|
readonly "Saving\u2026": "Saving…";
|
|
289
294
|
readonly Created: "Created";
|
|
290
|
-
readonly active: "
|
|
291
|
-
readonly disabled: "
|
|
295
|
+
readonly active: "Active";
|
|
296
|
+
readonly disabled: "Disabled";
|
|
292
297
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
293
298
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
294
299
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -296,6 +301,9 @@ export declare function redirects(_required: Record<string, never>, options?: Re
|
|
|
296
301
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
297
302
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
298
303
|
readonly "\"?": "\"?";
|
|
304
|
+
readonly manual: "Manual";
|
|
305
|
+
readonly auto_slug_change: "URL change";
|
|
306
|
+
readonly import: "Imported";
|
|
299
307
|
};
|
|
300
308
|
readonly pages: {
|
|
301
309
|
readonly list: {
|
|
@@ -15,6 +15,6 @@ export function RedirectsPage({ useRedirectsHook = useWiredRedirects } = {}) {
|
|
|
15
15
|
}
|
|
16
16
|
if (!redirects)
|
|
17
17
|
return _jsx("div", { className: "notice", children: t("Loading redirects…") });
|
|
18
|
-
return (_jsxs("div", { className: "page", children: [_jsxs("div", { className: "page-header", children: [_jsxs("div", { className: "page-header-text", children: [_jsx("p", { className: "page-kicker", children: t("Marketing") }), _jsx("h1", { className: "page-title", children: t("Redirects") }),
|
|
18
|
+
return (_jsxs("div", { className: "page", children: [_jsxs("div", { className: "page-header", children: [_jsxs("div", { className: "page-header-text", children: [_jsx("p", { className: "page-kicker", children: t("Marketing") }), _jsx("h1", { className: "page-title", children: t("Redirects") }), _jsx("p", { className: "page-description", children: t("Manage URL redirects, including those created automatically when a page's address changes.") })] }), _jsx("div", { className: "page-actions", children: headerActions })] }), error ? _jsx("div", { className: "notice error", children: describeApiError({ e: error, fallback: "request failed" }) }) : null, _jsxs("form", { className: "card form-measure", onSubmit: submitCreate, children: [_jsx("div", { className: "field-group", children: _jsxs("div", { className: "field-row", children: [_jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: "redirect-match-type", children: t("Match type") }), _jsxs("select", { id: "redirect-match-type", name: "matchType", defaultValue: "exact", ...agentHandle({ handle: "redirects-create-match-type" }, { role: "field", label: "New redirect's match type" }), children: [_jsx("option", { value: "exact", children: t("exact", { serverLabel: "exact" }) }), _jsx("option", { value: "prefix", children: t("prefix", { serverLabel: "prefix" }) }), _jsx("option", { value: "wildcard", children: t("wildcard", { serverLabel: "wildcard" }) })] })] }), _jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: "redirect-from-pattern", children: t("From path") }), _jsx("input", { id: "redirect-from-pattern", name: "fromPattern", placeholder: "/old-path", required: true, ...agentHandle({ handle: "redirects-create-from-pattern" }, { role: "field", label: "New redirect's source path or pattern" }) })] }), _jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: "redirect-to-target", children: t("To target") }), _jsx("input", { id: "redirect-to-target", name: "toTarget", placeholder: "/new-path or https://example.com/...", required: true, ...agentHandle({ handle: "redirects-create-to-target" }, { role: "field", label: "New redirect's destination path or URL" }) })] }), _jsxs("div", { className: "field", children: [_jsx("label", { className: "field-label", htmlFor: "redirect-status-code", children: t("Status code") }), _jsxs("select", { id: "redirect-status-code", name: "statusCode", defaultValue: "301", ...agentHandle({ handle: "redirects-create-status-code" }, { role: "field", label: "New redirect's HTTP status code" }), children: [_jsx("option", { value: "301", children: t("301 (permanent)") }), _jsx("option", { value: "302", children: t("302 (temporary)") }), _jsx("option", { value: "307", children: t("307 (temporary, method-preserving)") }), _jsx("option", { value: "308", children: t("308 (permanent, method-preserving)") })] })] })] }) }), _jsx("div", { className: "editor-actions form-actions", children: _jsx("button", { type: "submit", disabled: saving, ...agentHandle({ handle: "redirects-create-submit" }, { role: "button", label: "Add this redirect rule" }), children: saving ? t("Saving…") : t("Add redirect") }) })] }), _jsx(ImportRedirectsForm, { t: t, locale: locale }), _jsx(DataTable, { rows: redirects, rowKey: (rule) => rule.id, empty: _jsx("div", { className: "card", children: _jsx("div", { className: "empty-state", children: _jsx("p", { children: t("No redirect rules yet.") }) }) }), columns: columns }), _jsx(ConfirmDialog, { open: pendingDelete !== null, agentHandle: "redirects-delete", title: t("Delete redirect rule?"), body: deleteBody, confirmLabel: t("Delete"), destructive: true, pending: deletePending, onConfirm: confirmDelete, onCancel: cancelDelete })] }));
|
|
19
19
|
}
|
|
20
20
|
//# sourceMappingURL=RedirectsPage.js.map
|
|
@@ -16,8 +16,7 @@ export declare const redirectsModule: {
|
|
|
16
16
|
readonly Import: "Import";
|
|
17
17
|
readonly Marketing: "Marketing";
|
|
18
18
|
readonly Redirects: "Redirects";
|
|
19
|
-
readonly "
|
|
20
|
-
readonly ") also show up here.": ") also show up here.";
|
|
19
|
+
readonly "Manage URL redirects, including those created automatically when a page's address changes.": "Manage URL redirects, including those created automatically when a page's address changes.";
|
|
21
20
|
readonly "Match type": "Match type";
|
|
22
21
|
readonly "From path": "From path";
|
|
23
22
|
readonly "To target": "To target";
|
|
@@ -38,9 +37,9 @@ export declare const redirectsModule: {
|
|
|
38
37
|
readonly "Loading redirects\u2026": "Loading redirects…";
|
|
39
38
|
readonly "Not valid JSON.": "Not valid JSON.";
|
|
40
39
|
readonly "Must be a JSON array of rule objects.": "Must be a JSON array of rule objects.";
|
|
41
|
-
readonly exact: "
|
|
42
|
-
readonly prefix: "
|
|
43
|
-
readonly wildcard: "
|
|
40
|
+
readonly exact: "Exact match";
|
|
41
|
+
readonly prefix: "Starts with";
|
|
42
|
+
readonly wildcard: "Wildcard";
|
|
44
43
|
readonly Status: "Status";
|
|
45
44
|
readonly More: "More";
|
|
46
45
|
readonly Delete: "Delete";
|
|
@@ -48,8 +47,8 @@ export declare const redirectsModule: {
|
|
|
48
47
|
readonly Enable: "Enable";
|
|
49
48
|
readonly "Saving\u2026": "Saving…";
|
|
50
49
|
readonly Created: "Created";
|
|
51
|
-
readonly active: "
|
|
52
|
-
readonly disabled: "
|
|
50
|
+
readonly active: "Active";
|
|
51
|
+
readonly disabled: "Disabled";
|
|
53
52
|
readonly "{created} created, {failed} failed.": "{created} created, {failed} failed.";
|
|
54
53
|
readonly "Item {index} ({code})": "Item {index} ({code})";
|
|
55
54
|
readonly "Actions for redirect rule from \"{fromPattern}\"": "Actions for redirect rule from \"{fromPattern}\"";
|
|
@@ -57,6 +56,9 @@ export declare const redirectsModule: {
|
|
|
57
56
|
readonly " rule objects (1-500 items)": " rule objects (1-500 items)";
|
|
58
57
|
readonly "Delete the redirect rule from \"": "Delete the redirect rule from \"";
|
|
59
58
|
readonly "\"?": "\"?";
|
|
59
|
+
readonly manual: "Manual";
|
|
60
|
+
readonly auto_slug_change: "URL change";
|
|
61
|
+
readonly import: "Imported";
|
|
60
62
|
};
|
|
61
63
|
readonly pages: {
|
|
62
64
|
readonly list: {
|
|
@@ -22,10 +22,10 @@ export declare const seoMessagesEn: {
|
|
|
22
22
|
readonly Nofollow: "Nofollow";
|
|
23
23
|
readonly "OG title": "OG title";
|
|
24
24
|
readonly "OG description": "OG description";
|
|
25
|
-
readonly "OG image
|
|
25
|
+
readonly "OG image": "OG image";
|
|
26
26
|
readonly "Twitter title": "Twitter title";
|
|
27
27
|
readonly "Twitter description": "Twitter description";
|
|
28
|
-
readonly "Twitter image
|
|
28
|
+
readonly "Twitter image": "Twitter image";
|
|
29
29
|
readonly "Saving\u2026": "Saving…";
|
|
30
30
|
readonly "Save overrides": "Save overrides";
|
|
31
31
|
readonly "Per-entry SEO": "Per-entry SEO";
|
|
@@ -33,7 +33,7 @@ export declare const seoMessagesEn: {
|
|
|
33
33
|
readonly "Title template (must contain %s)": "Title template (must contain %s)";
|
|
34
34
|
readonly "Default meta description": "Default meta description";
|
|
35
35
|
readonly "Social sharing": "Social sharing";
|
|
36
|
-
readonly "Default Open Graph / Twitter image
|
|
36
|
+
readonly "Default Open Graph / Twitter image": "Default Open Graph / Twitter image";
|
|
37
37
|
readonly "Twitter @site handle": "Twitter @site handle";
|
|
38
38
|
readonly Crawling: "Crawling";
|
|
39
39
|
readonly "Default noindex": "Default noindex";
|
|
@@ -41,7 +41,7 @@ export declare const seoMessagesEn: {
|
|
|
41
41
|
readonly "Sitemap enabled": "Sitemap enabled";
|
|
42
42
|
readonly "Save settings": "Save settings";
|
|
43
43
|
readonly "Cached sitemap": "Cached sitemap";
|
|
44
|
-
readonly "
|
|
44
|
+
readonly "Rebuild the sitemap now to include the latest published content.": "Rebuild the sitemap now to include the latest published content.";
|
|
45
45
|
readonly "Working\u2026": "Working…";
|
|
46
46
|
readonly "Regenerate sitemap": "Regenerate sitemap";
|
|
47
47
|
readonly "View sitemap": "View sitemap";
|
|
@@ -74,5 +74,6 @@ export declare const seoMessagesEn: {
|
|
|
74
74
|
readonly "failed to regenerate sitemap": "failed to regenerate sitemap";
|
|
75
75
|
readonly "failed to load the sitemap": "failed to load the sitemap";
|
|
76
76
|
readonly "Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status}).";
|
|
77
|
+
readonly "Selected image": "Selected image";
|
|
77
78
|
};
|
|
78
79
|
//# sourceMappingURL=messages.en.d.ts.map
|
package/dist/seo/messages.en.js
CHANGED
|
@@ -22,10 +22,10 @@ export const seoMessagesEn = {
|
|
|
22
22
|
"Nofollow": "Nofollow",
|
|
23
23
|
"OG title": "OG title",
|
|
24
24
|
"OG description": "OG description",
|
|
25
|
-
"OG image
|
|
25
|
+
"OG image": "OG image",
|
|
26
26
|
"Twitter title": "Twitter title",
|
|
27
27
|
"Twitter description": "Twitter description",
|
|
28
|
-
"Twitter image
|
|
28
|
+
"Twitter image": "Twitter image",
|
|
29
29
|
"Saving…": "Saving…",
|
|
30
30
|
"Save overrides": "Save overrides",
|
|
31
31
|
"Per-entry SEO": "Per-entry SEO",
|
|
@@ -33,7 +33,7 @@ export const seoMessagesEn = {
|
|
|
33
33
|
"Title template (must contain %s)": "Title template (must contain %s)",
|
|
34
34
|
"Default meta description": "Default meta description",
|
|
35
35
|
"Social sharing": "Social sharing",
|
|
36
|
-
"Default Open Graph / Twitter image
|
|
36
|
+
"Default Open Graph / Twitter image": "Default Open Graph / Twitter image",
|
|
37
37
|
"Twitter @site handle": "Twitter @site handle",
|
|
38
38
|
"Crawling": "Crawling",
|
|
39
39
|
"Default noindex": "Default noindex",
|
|
@@ -41,7 +41,7 @@ export const seoMessagesEn = {
|
|
|
41
41
|
"Sitemap enabled": "Sitemap enabled",
|
|
42
42
|
"Save settings": "Save settings",
|
|
43
43
|
"Cached sitemap": "Cached sitemap",
|
|
44
|
-
"
|
|
44
|
+
"Rebuild the sitemap now to include the latest published content.": "Rebuild the sitemap now to include the latest published content.",
|
|
45
45
|
"Working…": "Working…",
|
|
46
46
|
"Regenerate sitemap": "Regenerate sitemap",
|
|
47
47
|
"View sitemap": "View sitemap",
|
|
@@ -73,6 +73,7 @@ export const seoMessagesEn = {
|
|
|
73
73
|
"Sitemap regeneration accepted.": "Sitemap regeneration accepted.",
|
|
74
74
|
"failed to regenerate sitemap": "failed to regenerate sitemap",
|
|
75
75
|
"failed to load the sitemap": "failed to load the sitemap",
|
|
76
|
-
"Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status})."
|
|
76
|
+
"Could not load the sitemap (HTTP {status}).": "Could not load the sitemap (HTTP {status}).",
|
|
77
|
+
"Selected image": "Selected image",
|
|
77
78
|
};
|
|
78
79
|
//# sourceMappingURL=messages.en.js.map
|
|
@@ -12,6 +12,10 @@ import { useWiredMediaRefField } from "../hooks/MediaRefField.hooks.js";
|
|
|
12
12
|
* `react/hooks/MediaRefField.hooks.ts`, split out the same way `MediaPickerDialog`/`MediaPickerDialog.hooks
|
|
13
13
|
* .tsx` does; this file stays props-and-JSX only. `MediaPickerDialog` itself is reused unchanged
|
|
14
14
|
* (`components/MediaPickerDialog/MediaPickerDialog.tsx`) — no fork, no new picker UI.
|
|
15
|
+
*
|
|
16
|
+
* 2026-10-08 polish: the original editable-input rationale above still applies to pasted URLs
|
|
17
|
+
* and empty fields. A selected library reference now shows plain copy with its preview; Remove
|
|
18
|
+
* returns to manual entry. A hidden input preserves the exact FormData value on defaults saves.
|
|
15
19
|
*/
|
|
16
20
|
export interface MediaRefFieldProps {
|
|
17
21
|
locale: string;
|
|
@@ -5,8 +5,8 @@ import { useSeoCopy } from "../hooks/SeoPorts.hooks.js";
|
|
|
5
5
|
import { useWiredMediaRefField, useMediaRefPresentation, handleSpread } from "../hooks/MediaRefField.hooks.js";
|
|
6
6
|
export function MediaRefField({ locale, id, name, label, value, onChange, agentHandle: base, useField = useWiredMediaRefField, }, _optional = {}) {
|
|
7
7
|
const t = useSeoCopy();
|
|
8
|
-
const { Picker = MediaPickerBridge } = useMediaRefPresentation();
|
|
8
|
+
const { Picker = MediaPickerBridge, storedReference } = useMediaRefPresentation({ value });
|
|
9
9
|
const { pickerOpen, openPicker, closePicker, handleSelect, clear, previewUrl, accept } = useField({ value, onChange });
|
|
10
|
-
return (_jsxs("div", { className: "field media-ref-field", children: [_jsx("label", { className: "field-label", htmlFor: id, children: label }), _jsxs("div", { className: "media-ref-field-row", children: [_jsx("input", { id: id, name: name, value: value, onChange: (e) => onChange(e.target.value), ...(base ? agentHandle({ handle: base }, { role: "field", label }) : {}) }), _jsx("button", { type: "button", className: "btn-secondary", onClick: openPicker, ...handleSpread({ ...(base === undefined ? {} : { base }), suffix: "choose", label: `Choose an image for: ${label}` }), children: t({ locale: locale, key: "Choose image" }) }), value ? (_jsx("button", { type: "button", className: "btn-secondary", onClick: clear, ...handleSpread({ ...(base === undefined ? {} : { base }), suffix: "clear", label: `Remove the selected image for: ${label}` }), children: t({ locale: locale, key: "Remove" }) })) : null] }), previewUrl ? _jsx("img", { className: "media-ref-field-preview", src: previewUrl, alt: `${label} preview` }) : null, pickerOpen ? (_jsx(Picker, { onSelect: handleSelect, onCancel: closePicker, accept: accept, agentHandle: base ? `${base}-dialog` : undefined })) : null] }));
|
|
10
|
+
return (_jsxs("div", { className: "jini-field jini-media-ref-field", children: [_jsx("label", { className: "jini-field-label", htmlFor: id, children: label }), _jsxs("div", { className: "jini-media-ref-field-row", children: [_jsx("input", { className: "jini-input", id: id, name: storedReference ? undefined : name, value: storedReference ? t({ locale, key: "Selected image" }) : value, readOnly: storedReference, onChange: (e) => onChange(e.target.value), ...(base ? agentHandle({ handle: base }, { role: "field", label }) : {}) }), storedReference && name ? _jsx("input", { type: "hidden", name: name, value: value }) : null, _jsx("button", { type: "button", className: "jini-btn jini-btn-secondary", onClick: openPicker, ...handleSpread({ ...(base === undefined ? {} : { base }), suffix: "choose", label: `Choose an image for: ${label}` }), children: t({ locale: locale, key: "Choose image" }) }), value ? (_jsx("button", { type: "button", className: "jini-btn jini-btn-secondary", onClick: clear, ...handleSpread({ ...(base === undefined ? {} : { base }), suffix: "clear", label: `Remove the selected image for: ${label}` }), children: t({ locale: locale, key: "Remove" }) })) : null] }), previewUrl ? _jsx("img", { className: "jini-media-ref-field-preview", src: previewUrl, alt: `${label} preview` }) : null, pickerOpen ? (_jsx(Picker, { onSelect: handleSelect, onCancel: closePicker, accept: accept, agentHandle: base ? `${base}-dialog` : undefined })) : null] }));
|
|
11
11
|
}
|
|
12
12
|
//# sourceMappingURL=MediaRefField.js.map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { agentHandle } from "@jini-ai/agentic";
|
|
3
3
|
import { Dialog } from "@jini-ai/ui-kit/react";
|
|
4
|
-
import {
|
|
4
|
+
import { formatTimestamp } from "@jini-ai/ui/panel-kit";
|
|
5
|
+
import { useSeoCopy, useSeoOptions } from "../hooks/SeoPorts.hooks.js";
|
|
5
6
|
import { actionLabel } from "../../rules.js";
|
|
6
7
|
import { useWiredSitemapModal } from "../hooks/use-sitemap-modal.hooks.js";
|
|
7
8
|
import { useSitemapModalRegenerate, useSitemapPresentation, useSitemapTable, useSitemapViewToggle } from "../hooks/SitemapModal.hooks.js";
|
|
@@ -30,13 +31,14 @@ function SitemapModalHeaderActions({ locale, modal }) {
|
|
|
30
31
|
* `useSitemapModal` (memoized there), this only maps them to JSX. */
|
|
31
32
|
function SitemapModalTable({ locale, modal }) {
|
|
32
33
|
const t = useSeoCopy();
|
|
34
|
+
const { formatDate = formatTimestamp } = useSeoOptions();
|
|
33
35
|
const { rowHandles } = useSitemapTable({ modal });
|
|
34
36
|
if (modal.entries.length === 0)
|
|
35
37
|
return _jsx("div", { className: "notice", children: t({ locale: locale, key: "The sitemap has no URLs yet." }) });
|
|
36
38
|
return (_jsxs(_Fragment, { children: [_jsx("input", { type: "search", className: "sitemap-modal-filter", "aria-label": t({ locale: locale, key: "Filter sitemap URLs" }), placeholder: t({ locale: locale, key: "Filter by URL…" }), value: modal.filter, onChange: (e) => modal.setFilter(e.target.value), ...agentHandle({ handle: "seo-sitemap-filter" }, {
|
|
37
39
|
role: "field",
|
|
38
40
|
label: "Narrow the sitemap table by a substring match on the URL",
|
|
39
|
-
}) }), modal.filteredEntries.length === 0 ? (_jsx("p", { className: "muted-cell", children: t({ locale: locale, key: "No URLs match this filter." }) })) : (_jsx("div", { className: "table-scroll", children: _jsxs("table", { className: "list-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: t({ locale: locale, key: "URL" }) }), _jsx("th", { children: t({ locale: locale, key: "Last modified" }) })] }) }), _jsx("tbody", { children: modal.filteredEntries.map((entry, index) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx("a", { href: entry.loc, target: "_blank", rel: "noreferrer", ...agentHandle({ handle: rowHandles[index] }, { role: "link", label: "Open this URL on the live site" }), children: entry.loc }) }), _jsx("td", { children: entry.lastmod
|
|
41
|
+
}) }), modal.filteredEntries.length === 0 ? (_jsx("p", { className: "muted-cell", children: t({ locale: locale, key: "No URLs match this filter." }) })) : (_jsx("div", { className: "table-scroll", children: _jsxs("table", { className: "list-table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: t({ locale: locale, key: "URL" }) }), _jsx("th", { children: t({ locale: locale, key: "Last modified" }) })] }) }), _jsx("tbody", { children: modal.filteredEntries.map((entry, index) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx("a", { href: entry.loc, target: "_blank", rel: "noreferrer", ...agentHandle({ handle: rowHandles[index] }, { role: "link", label: "Open this URL on the live site" }), children: entry.loc }) }), _jsx("td", { children: entry.lastmod === null ? _jsx("span", { className: "muted-cell", children: t({ locale: locale, key: "—" }) }) : formatDate({ iso: entry.lastmod }) })] }, entry.loc))) })] }) }))] }));
|
|
40
42
|
}
|
|
41
43
|
/** The body's content-status switch (REQ 8/9: disabled, loading, error, then raw-vs-table) — kept
|
|
42
44
|
* as its own flat sequence of guards rather than a nested ternary inline in {@link SitemapModal}.
|
|
@@ -11,8 +11,11 @@ export declare function useWiredMediaRefField({ value, onChange }: {
|
|
|
11
11
|
onChange: (value: string) => void;
|
|
12
12
|
}, _optional?: Record<string, never>): MediaRefFieldController;
|
|
13
13
|
/** Slot or existing promise picker; no picker implementation is forked into SEO. */
|
|
14
|
-
export declare function useMediaRefPresentation(
|
|
14
|
+
export declare function useMediaRefPresentation({ value }: {
|
|
15
|
+
value: string;
|
|
16
|
+
}, _optional?: Record<string, never>): {
|
|
15
17
|
Picker: import("react").ComponentType<import("../options.js").SeoMediaPickerSlotProps> | undefined;
|
|
18
|
+
storedReference: boolean;
|
|
16
19
|
};
|
|
17
20
|
export declare function handleSpread({ base, suffix, label }: {
|
|
18
21
|
base?: string;
|
|
@@ -2,7 +2,7 @@ import { useRef } from 'react';
|
|
|
2
2
|
import { agentHandle } from '@jini-ai/agentic';
|
|
3
3
|
import { useController } from '../../../core/react/use-controller.js';
|
|
4
4
|
import { createMediaRefController } from '../../controllers/media-ref.controller.js';
|
|
5
|
-
import { resolveMediaRefPreviewUrl } from '../../rules.js';
|
|
5
|
+
import { isStoredMediaRef, resolveMediaRefPreviewUrl } from '../../rules.js';
|
|
6
6
|
import { useSeoPorts, useSeoOptions } from './SeoPorts.hooks.js';
|
|
7
7
|
export function useMediaRefField({ value, onChange, api }, _optional = {}) {
|
|
8
8
|
const change = useRef(onChange);
|
|
@@ -20,9 +20,9 @@ export function useWiredMediaRefField({ value, onChange }, _optional = {}) {
|
|
|
20
20
|
return useMediaRefField({ value, onChange, api });
|
|
21
21
|
}
|
|
22
22
|
/** Slot or existing promise picker; no picker implementation is forked into SEO. */
|
|
23
|
-
export function useMediaRefPresentation(
|
|
23
|
+
export function useMediaRefPresentation({ value }, _optional = {}) {
|
|
24
24
|
const { slots } = useSeoOptions();
|
|
25
|
-
return { Picker: slots?.MediaPickerDialog };
|
|
25
|
+
return { Picker: slots?.MediaPickerDialog, storedReference: isStoredMediaRef({ value }) };
|
|
26
26
|
}
|
|
27
27
|
export function handleSpread({ base, suffix, label }, _optional = {}) {
|
|
28
28
|
return base ? agentHandle({ handle: `${base}-${suffix}` }, { role: 'button', label }) : {};
|