@prenta/admin 2.7.0 → 2.8.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/CHANGELOG.md +34 -0
- package/design-system/tokens.css +17 -0
- package/design-system/tokens.json +35 -1
- package/design-system/tokens.scss +15 -0
- package/design-system/tokens.tailwind.cjs +14 -0
- package/dist/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js +2 -2
- package/dist/AdminRoot.js.map +1 -1
- package/dist/__tests__/lib/batch-wizard.test.d.ts +2 -0
- package/dist/__tests__/lib/batch-wizard.test.d.ts.map +1 -0
- package/dist/__tests__/lib/batch-wizard.test.js +144 -0
- package/dist/__tests__/lib/batch-wizard.test.js.map +1 -0
- package/dist/__tests__/lib/job-drawer.test.js +2 -0
- package/dist/__tests__/lib/job-drawer.test.js.map +1 -1
- package/dist/__tests__/lib/job-view.test.js +100 -3
- package/dist/__tests__/lib/job-view.test.js.map +1 -1
- package/dist/__tests__/lib/jobs-service.test.js +56 -2
- package/dist/__tests__/lib/jobs-service.test.js.map +1 -1
- package/dist/__tests__/views/appearance-chrome.render.test.d.ts +2 -0
- package/dist/__tests__/views/appearance-chrome.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/appearance-chrome.render.test.js +688 -0
- package/dist/__tests__/views/appearance-chrome.render.test.js.map +1 -0
- package/dist/__tests__/views/header-footer-form.test.d.ts +2 -0
- package/dist/__tests__/views/header-footer-form.test.d.ts.map +1 -0
- package/dist/__tests__/views/header-footer-form.test.js +266 -0
- package/dist/__tests__/views/header-footer-form.test.js.map +1 -0
- package/dist/__tests__/views/jobs-drawer.render.test.js +442 -2
- package/dist/__tests__/views/jobs-drawer.render.test.js.map +1 -1
- package/dist/__tests__/views/jobs-list.render.test.js +7 -5
- package/dist/__tests__/views/jobs-list.render.test.js.map +1 -1
- package/dist/__tests__/views/jobs-wizard.render.test.d.ts +2 -0
- package/dist/__tests__/views/jobs-wizard.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/jobs-wizard.render.test.js +588 -0
- package/dist/__tests__/views/jobs-wizard.render.test.js.map +1 -0
- package/dist/lib/api.d.ts +2 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +8 -1
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/batch-wizard.d.ts +84 -0
- package/dist/lib/batch-wizard.d.ts.map +1 -0
- package/dist/lib/batch-wizard.js +122 -0
- package/dist/lib/batch-wizard.js.map +1 -0
- package/dist/lib/chrome-service.d.ts +69 -0
- package/dist/lib/chrome-service.d.ts.map +1 -0
- package/dist/lib/chrome-service.js +108 -0
- package/dist/lib/chrome-service.js.map +1 -0
- package/dist/lib/job-view.d.ts +43 -0
- package/dist/lib/job-view.d.ts.map +1 -1
- package/dist/lib/job-view.js +57 -1
- package/dist/lib/job-view.js.map +1 -1
- package/dist/lib/jobs-service.d.ts +19 -1
- package/dist/lib/jobs-service.d.ts.map +1 -1
- package/dist/lib/jobs-service.js +41 -0
- package/dist/lib/jobs-service.js.map +1 -1
- package/dist/prenta-admin.css +1 -1
- package/dist/views/AppearanceChrome.d.ts +22 -4
- package/dist/views/AppearanceChrome.d.ts.map +1 -1
- package/dist/views/AppearanceChrome.js +451 -15
- package/dist/views/AppearanceChrome.js.map +1 -1
- package/dist/views/Jobs/CancelJobDialog.d.ts +7 -1
- package/dist/views/Jobs/CancelJobDialog.d.ts.map +1 -1
- package/dist/views/Jobs/CancelJobDialog.js +13 -3
- package/dist/views/Jobs/CancelJobDialog.js.map +1 -1
- package/dist/views/Jobs/DrawerReview.d.ts +7 -0
- package/dist/views/Jobs/DrawerReview.d.ts.map +1 -1
- package/dist/views/Jobs/DrawerReview.js +1 -1
- package/dist/views/Jobs/DrawerReview.js.map +1 -1
- package/dist/views/Jobs/JobDrawer.d.ts +23 -3
- package/dist/views/Jobs/JobDrawer.d.ts.map +1 -1
- package/dist/views/Jobs/JobDrawer.js +30 -5
- package/dist/views/Jobs/JobDrawer.js.map +1 -1
- package/dist/views/Jobs/JobsTable.d.ts +4 -2
- package/dist/views/Jobs/JobsTable.d.ts.map +1 -1
- package/dist/views/Jobs/JobsTable.js +6 -5
- package/dist/views/Jobs/JobsTable.js.map +1 -1
- package/dist/views/Jobs/NewBatchJob.d.ts +34 -0
- package/dist/views/Jobs/NewBatchJob.d.ts.map +1 -0
- package/dist/views/Jobs/NewBatchJob.js +282 -0
- package/dist/views/Jobs/NewBatchJob.js.map +1 -0
- package/dist/views/Jobs/WorkerStrip.d.ts +3 -1
- package/dist/views/Jobs/WorkerStrip.d.ts.map +1 -1
- package/dist/views/Jobs/WorkerStrip.js +2 -2
- package/dist/views/Jobs/WorkerStrip.js.map +1 -1
- package/dist/views/Jobs/focus.d.ts +6 -0
- package/dist/views/Jobs/focus.d.ts.map +1 -1
- package/dist/views/Jobs/focus.js +10 -0
- package/dist/views/Jobs/focus.js.map +1 -1
- package/dist/views/Jobs.d.ts +12 -3
- package/dist/views/Jobs.d.ts.map +1 -1
- package/dist/views/Jobs.js +109 -31
- package/dist/views/Jobs.js.map +1 -1
- package/dist/views/header-footer/AnnouncementTab.d.ts +15 -0
- package/dist/views/header-footer/AnnouncementTab.d.ts.map +1 -0
- package/dist/views/header-footer/AnnouncementTab.js +43 -0
- package/dist/views/header-footer/AnnouncementTab.js.map +1 -0
- package/dist/views/header-footer/ChromeField.d.ts +25 -0
- package/dist/views/header-footer/ChromeField.d.ts.map +1 -0
- package/dist/views/header-footer/ChromeField.js +99 -0
- package/dist/views/header-footer/ChromeField.js.map +1 -0
- package/dist/views/header-footer/ChromePreview.d.ts +31 -0
- package/dist/views/header-footer/ChromePreview.d.ts.map +1 -0
- package/dist/views/header-footer/ChromePreview.js +195 -0
- package/dist/views/header-footer/ChromePreview.js.map +1 -0
- package/dist/views/header-footer/DeveloperTab.d.ts +17 -0
- package/dist/views/header-footer/DeveloperTab.d.ts.map +1 -0
- package/dist/views/header-footer/DeveloperTab.js +98 -0
- package/dist/views/header-footer/DeveloperTab.js.map +1 -0
- package/dist/views/header-footer/RegionTab.d.ts +27 -0
- package/dist/views/header-footer/RegionTab.d.ts.map +1 -0
- package/dist/views/header-footer/RegionTab.js +80 -0
- package/dist/views/header-footer/RegionTab.js.map +1 -0
- package/dist/views/header-footer/chrome-form.d.ts +137 -0
- package/dist/views/header-footer/chrome-form.d.ts.map +1 -0
- package/dist/views/header-footer/chrome-form.js +518 -0
- package/dist/views/header-footer/chrome-form.js.map +1 -0
- package/dist/views/header-footer/code-samples.d.ts +30 -0
- package/dist/views/header-footer/code-samples.d.ts.map +1 -0
- package/dist/views/header-footer/code-samples.js +127 -0
- package/dist/views/header-footer/code-samples.js.map +1 -0
- package/dist/views/header-footer/controls.d.ts +57 -0
- package/dist/views/header-footer/controls.d.ts.map +1 -0
- package/dist/views/header-footer/controls.js +43 -0
- package/dist/views/header-footer/controls.js.map +1 -0
- package/package.json +3 -3
- package/src/AdminRoot.tsx +16 -2
- package/src/__tests__/lib/batch-wizard.test.ts +199 -0
- package/src/__tests__/lib/job-drawer.test.ts +2 -0
- package/src/__tests__/lib/job-view.test.ts +123 -2
- package/src/__tests__/lib/jobs-service.test.ts +72 -3
- package/src/__tests__/views/appearance-chrome.render.test.tsx +818 -0
- package/src/__tests__/views/header-footer-form.test.ts +333 -0
- package/src/__tests__/views/jobs-drawer.render.test.tsx +508 -2
- package/src/__tests__/views/jobs-list.render.test.tsx +8 -5
- package/src/__tests__/views/jobs-wizard.render.test.tsx +707 -0
- package/src/lib/api.ts +12 -1
- package/src/lib/batch-wizard.ts +188 -0
- package/src/lib/chrome-service.ts +200 -0
- package/src/lib/job-view.ts +95 -1
- package/src/lib/jobs-service.ts +56 -1
- package/src/styles/prenta-tokens.css +17 -0
- package/src/styles/theme.css +15 -0
- package/src/views/AppearanceChrome.tsx +704 -46
- package/src/views/Jobs/CancelJobDialog.tsx +20 -2
- package/src/views/Jobs/DrawerReview.tsx +1 -1
- package/src/views/Jobs/JobDrawer.tsx +83 -3
- package/src/views/Jobs/JobsTable.tsx +11 -4
- package/src/views/Jobs/NewBatchJob.tsx +857 -0
- package/src/views/Jobs/WorkerStrip.tsx +16 -11
- package/src/views/Jobs/focus.ts +11 -0
- package/src/views/Jobs.tsx +163 -49
- package/src/views/header-footer/AnnouncementTab.tsx +231 -0
- package/src/views/header-footer/ChromeField.tsx +358 -0
- package/src/views/header-footer/ChromePreview.tsx +497 -0
- package/src/views/header-footer/DeveloperTab.tsx +331 -0
- package/src/views/header-footer/RegionTab.tsx +398 -0
- package/src/views/header-footer/chrome-form.ts +603 -0
- package/src/views/header-footer/code-samples.ts +146 -0
- package/src/views/header-footer/controls.tsx +166 -0
- package/dist/views/Jobs/placeholders.d.ts +0 -6
- package/dist/views/Jobs/placeholders.d.ts.map +0 -1
- package/dist/views/Jobs/placeholders.js +0 -20
- package/dist/views/Jobs/placeholders.js.map +0 -1
- package/src/views/Jobs/placeholders.tsx +0 -66
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Developer tab's "How it's wired" samples: the kit's `CODE` strings
|
|
3
|
+
* (appearance-hf.jsx), with the names this repo ships. `@prenta/sdk` doesn't
|
|
4
|
+
* exist; `defineRegion` and `field` are on `@prenta/core/config`, the Astro
|
|
5
|
+
* helpers on `@prenta/core/astro/site`, `<Announcement>` on
|
|
6
|
+
* `@prenta/client/react`, and the public endpoint is `/public/chrome` inside
|
|
7
|
+
* the `{ data }` envelope (CONFLICTS.md §3).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type CodeSampleId = 'config' | 'render' | 'api'
|
|
11
|
+
|
|
12
|
+
export interface CodeSample {
|
|
13
|
+
id: CodeSampleId
|
|
14
|
+
/** The segmented control's label. */
|
|
15
|
+
label: string
|
|
16
|
+
/** The caption over the code. */
|
|
17
|
+
file: string
|
|
18
|
+
src: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const CODE_SAMPLES: readonly CodeSample[] = [
|
|
22
|
+
{
|
|
23
|
+
id: 'config',
|
|
24
|
+
label: 'Schema',
|
|
25
|
+
file: 'prenta.config.ts',
|
|
26
|
+
src: `import { defineRegion, field } from '@prenta/core/config';
|
|
27
|
+
|
|
28
|
+
// Markup stays in your components. This only declares
|
|
29
|
+
// what editors can change. Saved values are typed.
|
|
30
|
+
export const header = defineRegion('header', {
|
|
31
|
+
component: './src/components/site/Header.astro',
|
|
32
|
+
variants: {
|
|
33
|
+
default: 'Logo left, menu right',
|
|
34
|
+
centered: 'Centered logo',
|
|
35
|
+
minimal: 'Logo + CTA', // landing pages
|
|
36
|
+
},
|
|
37
|
+
fields: {
|
|
38
|
+
logo: field.brand('logo'), // read-only, from Settings
|
|
39
|
+
menu: field.menu({ default: 'main' }),
|
|
40
|
+
cta: field.link({ optional: true }),
|
|
41
|
+
phone: field.text({ optional: true, format: 'tel' }),
|
|
42
|
+
topMenu: field.menu({ optional: true, label: 'Top bar' }),
|
|
43
|
+
search: field.boolean({ default: false }),
|
|
44
|
+
sticky: field.boolean({ default: true }),
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const footer = defineRegion('footer', {
|
|
49
|
+
component: './src/components/site/Footer.astro',
|
|
50
|
+
variants: { columns: 'Columns', compact: 'Compact', minimal: 'Single line' },
|
|
51
|
+
fields: {
|
|
52
|
+
tone: field.select(['dark', 'light'], { default: 'dark' }),
|
|
53
|
+
about: field.textarea({ max: 200 }),
|
|
54
|
+
cols: field.menu({ list: true, max: 3 }),
|
|
55
|
+
social: field.social(),
|
|
56
|
+
legalMenu: field.menu({ optional: true }),
|
|
57
|
+
copy: field.text({ tokens: ['{year}'] }),
|
|
58
|
+
},
|
|
59
|
+
});`,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'render',
|
|
63
|
+
label: 'Layout',
|
|
64
|
+
file: 'src/layouts/Base.astro',
|
|
65
|
+
src: `---
|
|
66
|
+
import { createAstroSiteHelpers } from '@prenta/core/astro/site';
|
|
67
|
+
import { Announcement } from '@prenta/client/react'; // headless, unstyled
|
|
68
|
+
import Header from '../components/site/Header.astro';
|
|
69
|
+
import Footer from '../components/site/Footer.astro';
|
|
70
|
+
|
|
71
|
+
// Resolves site defaults + page overrides + schedule in one call.
|
|
72
|
+
const { getChrome } = createAstroSiteHelpers();
|
|
73
|
+
const { header, footer, announcement } = (await getChrome(Astro.url.pathname)) ?? {};
|
|
74
|
+
---
|
|
75
|
+
<Announcement data={announcement} className="ann" client:load /> <!-- or render your own -->
|
|
76
|
+
{header && <Header variant={header.variant} {...header.fields} />}
|
|
77
|
+
<slot />
|
|
78
|
+
{footer && <Footer variant={footer.variant} {...footer.fields} />}`,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: 'api',
|
|
82
|
+
label: 'API',
|
|
83
|
+
file: 'GET /api/cms/public/chrome?path=/seo-audit',
|
|
84
|
+
src: `{
|
|
85
|
+
"data": {
|
|
86
|
+
"header": {
|
|
87
|
+
"variant": "minimal", // page override wins
|
|
88
|
+
"fields": {
|
|
89
|
+
"logo": { ... }, // from Settings > Brand
|
|
90
|
+
"menu": { "id": "main", "name": "Main", "items": [ ... ] },
|
|
91
|
+
"cta": { "label": "Get a free audit", "url": "/seo-audit" },
|
|
92
|
+
"phone": "(757) 555-0100",
|
|
93
|
+
"topMenu": null,
|
|
94
|
+
"search": false,
|
|
95
|
+
"sticky": true
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"footer": { "variant": "columns", "fields": { ... } },
|
|
99
|
+
"announcement": {
|
|
100
|
+
"id": "ann_8f2c41d0", // changes when the message changes
|
|
101
|
+
"text": "Free SEO audits are back for Q4. Limited spots.",
|
|
102
|
+
"link": { "label": "Book yours", "url": "/seo-audit" },
|
|
103
|
+
"tone": "brand", // style it with your tokens
|
|
104
|
+
"dismissible": true,
|
|
105
|
+
"endsAt": null
|
|
106
|
+
},
|
|
107
|
+
"etag": "W/\\"chrome-6b1f0c2e9a4d\\""
|
|
108
|
+
}
|
|
109
|
+
}`,
|
|
110
|
+
},
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
export const LOCAL_DEV_SAMPLE = `npx prenta pull chrome // writes .prenta/chrome.json
|
|
114
|
+
npx prenta types // generates ChromeFields types`
|
|
115
|
+
|
|
116
|
+
export type CodeTokenKind = 'comment' | 'string' | 'keyword' | 'plain'
|
|
117
|
+
|
|
118
|
+
export interface CodeToken {
|
|
119
|
+
kind: CodeTokenKind
|
|
120
|
+
text: string
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const LITERALS = /(\/\/[^\n]*|<!--[^\n]*-->|'[^'\n]*'|"(?:[^"\\\n]|\\.)*")/g
|
|
124
|
+
const KEYWORDS = /\b(import|from|export|const|await)\b/g
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The kit's highlighter (`hl`): comments, then strings, then a few keywords.
|
|
128
|
+
* Joining the tokens' text gives back the source exactly.
|
|
129
|
+
*/
|
|
130
|
+
export function highlight(src: string): CodeToken[] {
|
|
131
|
+
const tokens: CodeToken[] = []
|
|
132
|
+
src.split(LITERALS).forEach((part, index) => {
|
|
133
|
+
if (!part) return
|
|
134
|
+
if (index % 2 === 1) {
|
|
135
|
+
tokens.push({
|
|
136
|
+
kind: part.startsWith('//') || part.startsWith('<!--') ? 'comment' : 'string',
|
|
137
|
+
text: part,
|
|
138
|
+
})
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
part.split(KEYWORDS).forEach((piece, j) => {
|
|
142
|
+
if (piece) tokens.push({ kind: j % 2 === 1 ? 'keyword' : 'plain', text: piece })
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
return tokens
|
|
146
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { Lock } from 'lucide-react'
|
|
4
|
+
import type { ReactNode } from 'react'
|
|
5
|
+
|
|
6
|
+
/** `.ap-in`: 34px, radius 8, 13px; `.ap-in.mono` is 12px DM Mono. */
|
|
7
|
+
export const INPUT =
|
|
8
|
+
'rounded-8 border-bdr bg-card text-body text-txt placeholder:text-faint focus-visible:border-acc-m h-[34px] w-full min-w-0 border px-2.5 leading-[normal] disabled:cursor-not-allowed disabled:opacity-60'
|
|
9
|
+
export const MONO = 'font-mono text-[12px]'
|
|
10
|
+
/** `.ap-in` as a multi-line box (the kit's textarea). */
|
|
11
|
+
export const TEXTAREA =
|
|
12
|
+
'rounded-8 border-bdr bg-card text-body text-txt focus-visible:border-acc-m min-h-[60px] w-full min-w-0 resize-y border px-2.5 py-2 leading-[1.45] disabled:cursor-not-allowed disabled:opacity-60'
|
|
13
|
+
|
|
14
|
+
/** `.ap-lb`: 12px / 600, 5px above the control. */
|
|
15
|
+
export function FieldLabel({ htmlFor, children }: { htmlFor?: string; children: ReactNode }) {
|
|
16
|
+
return (
|
|
17
|
+
<label htmlFor={htmlFor} className="text-meta text-txt mb-[5px] block font-semibold">
|
|
18
|
+
{children}
|
|
19
|
+
</label>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** `.ap-help`: 11.5px --muted, 5px under the control. */
|
|
24
|
+
export function Help({
|
|
25
|
+
id,
|
|
26
|
+
tone = 'muted',
|
|
27
|
+
children,
|
|
28
|
+
}: {
|
|
29
|
+
id?: string
|
|
30
|
+
tone?: 'muted' | 'error'
|
|
31
|
+
children: ReactNode
|
|
32
|
+
}) {
|
|
33
|
+
return (
|
|
34
|
+
<div
|
|
35
|
+
id={id}
|
|
36
|
+
className={`text-hint mt-[5px] leading-[1.45] ${tone === 'error' ? 'text-err' : 'text-faint'}`}
|
|
37
|
+
>
|
|
38
|
+
{children}
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** `.hf-key`: a field key or id as a mono chip. */
|
|
44
|
+
export function KeyChip({
|
|
45
|
+
children,
|
|
46
|
+
bare = false,
|
|
47
|
+
size = 11,
|
|
48
|
+
}: {
|
|
49
|
+
children: ReactNode
|
|
50
|
+
bare?: boolean
|
|
51
|
+
/** 11px; a variant card's id is 10.5px. */
|
|
52
|
+
size?: 11 | 10.5
|
|
53
|
+
}) {
|
|
54
|
+
return (
|
|
55
|
+
<code
|
|
56
|
+
// 500: the admin ships DM Mono at 400 and 500 only, so 600 would be synthesized.
|
|
57
|
+
className={`text-faint overflow-hidden font-mono font-medium text-ellipsis whitespace-nowrap ${
|
|
58
|
+
size === 11 ? 'text-[11px]' : 'text-[10.5px]'
|
|
59
|
+
} ${bare ? '' : 'rounded-5 border-bdr bg-bg border px-1.5'}`}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
</code>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** `.hf-lock`: "Defined in code". */
|
|
67
|
+
export function LockPill({ children }: { children: ReactNode }) {
|
|
68
|
+
return (
|
|
69
|
+
<span className="rounded-pill border-bdr bg-bg text-faint inline-flex items-center gap-1 border px-[7px] text-[10.5px] leading-[normal] font-[650] whitespace-nowrap">
|
|
70
|
+
<Lock size={11} strokeWidth={1.8} aria-hidden />
|
|
71
|
+
{children}
|
|
72
|
+
</span>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface PillOption {
|
|
77
|
+
id: string
|
|
78
|
+
label: string
|
|
79
|
+
/** A 12px swatch before the label (announcement tones). */
|
|
80
|
+
swatch?: string
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* `.mn-chks` / `.mn-chk`: radio pills. 12.5px, radius 99, padding 3px 10px
|
|
85
|
+
* 3px 8px; the checked pill has an --acc border on --acc-l.
|
|
86
|
+
*/
|
|
87
|
+
export function RadioPills({
|
|
88
|
+
name,
|
|
89
|
+
label,
|
|
90
|
+
options,
|
|
91
|
+
value,
|
|
92
|
+
onChange,
|
|
93
|
+
disabled,
|
|
94
|
+
}: {
|
|
95
|
+
name: string
|
|
96
|
+
/** Accessible name for the group. */
|
|
97
|
+
label: string
|
|
98
|
+
options: readonly PillOption[]
|
|
99
|
+
value: string
|
|
100
|
+
onChange: (id: string) => void
|
|
101
|
+
disabled?: boolean
|
|
102
|
+
}) {
|
|
103
|
+
return (
|
|
104
|
+
<div role="radiogroup" aria-label={label} className="flex flex-wrap gap-1.5">
|
|
105
|
+
{options.map((option) => {
|
|
106
|
+
const checked = option.id === value
|
|
107
|
+
return (
|
|
108
|
+
<label
|
|
109
|
+
key={option.id}
|
|
110
|
+
className={`rounded-pill text-sm2 text-txt inline-flex items-center gap-1.5 border py-[3px] pr-2.5 pl-2 leading-[normal] whitespace-nowrap ${
|
|
111
|
+
checked ? 'border-acc bg-acc-l' : 'border-bdr'
|
|
112
|
+
} ${disabled ? 'cursor-not-allowed opacity-60' : 'cursor-pointer'}`}
|
|
113
|
+
>
|
|
114
|
+
<input
|
|
115
|
+
type="radio"
|
|
116
|
+
name={name}
|
|
117
|
+
value={option.id}
|
|
118
|
+
checked={checked}
|
|
119
|
+
disabled={disabled}
|
|
120
|
+
onChange={() => onChange(option.id)}
|
|
121
|
+
className="accent-acc m-0"
|
|
122
|
+
/>
|
|
123
|
+
{option.swatch ? (
|
|
124
|
+
<i
|
|
125
|
+
aria-hidden
|
|
126
|
+
className="inline-block h-3 w-3 rounded-[3px]"
|
|
127
|
+
style={{ background: option.swatch }}
|
|
128
|
+
/>
|
|
129
|
+
) : null}
|
|
130
|
+
{option.label}
|
|
131
|
+
</label>
|
|
132
|
+
)
|
|
133
|
+
})}
|
|
134
|
+
</div>
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** A card heading row (`.ap-ch`) with the title, a subline and an optional right slot. */
|
|
139
|
+
export function CardHead({
|
|
140
|
+
title,
|
|
141
|
+
description,
|
|
142
|
+
id,
|
|
143
|
+
children,
|
|
144
|
+
}: {
|
|
145
|
+
title: string
|
|
146
|
+
description?: ReactNode
|
|
147
|
+
id?: string
|
|
148
|
+
children?: ReactNode
|
|
149
|
+
}) {
|
|
150
|
+
return (
|
|
151
|
+
<div className="border-bdr flex items-center gap-2.5 border-b px-4 py-[13px]">
|
|
152
|
+
<div className="min-w-0 flex-1">
|
|
153
|
+
<h2 id={id} className="text-card-title text-txt m-0 leading-[normal] font-[650]">
|
|
154
|
+
{title}
|
|
155
|
+
</h2>
|
|
156
|
+
{description ? (
|
|
157
|
+
<p className="text-meta text-sub m-0 mt-px leading-[normal]">{description}</p>
|
|
158
|
+
) : null}
|
|
159
|
+
</div>
|
|
160
|
+
{children}
|
|
161
|
+
</div>
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** `.ap-card`: --card, 1px --bdr, radius 12, --shd. */
|
|
166
|
+
export const CARD = 'rounded-12 border-bdr bg-card shadow-shd text-txt min-w-0 border'
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export interface NewBatchJobProps {
|
|
2
|
-
onClose: () => void;
|
|
3
|
-
}
|
|
4
|
-
/** The new batch AI job wizard. Until then, batches start from a list's bulk actions. */
|
|
5
|
-
export declare function NewBatchJob({ onClose }: NewBatchJobProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
-
//# sourceMappingURL=placeholders.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"placeholders.d.ts","sourceRoot":"","sources":["../../../src/views/Jobs/placeholders.tsx"],"names":[],"mappings":"AAmDA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,gBAAgB,2CASxD"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import * as Dialog from '@radix-ui/react-dialog';
|
|
4
|
-
import { Button } from '../../components/ui/Button.js';
|
|
5
|
-
import { adminPortalContainer } from '../../lib/portal-container.js';
|
|
6
|
-
import { useReturnFocus } from './focus.js';
|
|
7
|
-
/*
|
|
8
|
-
* Stand-in until the batch wizard (P-20, jobs-new.jsx) is built. The list
|
|
9
|
-
* already opens it with the props the kit passes, so it's swapped by
|
|
10
|
-
* replacing the component here.
|
|
11
|
-
*/
|
|
12
|
-
function StandIn({ title, description, onClose, onFocusFallback, }) {
|
|
13
|
-
const returnFocus = useReturnFocus(onFocusFallback);
|
|
14
|
-
return (_jsx(Dialog.Root, { open: true, onOpenChange: (open) => (open ? undefined : onClose()), children: _jsxs(Dialog.Portal, { container: adminPortalContainer(), children: [_jsx(Dialog.Overlay, { className: "bg-scrim-drawer fixed inset-0 z-[var(--z-modal)]" }), _jsxs(Dialog.Content, { ...returnFocus, className: "bg-card border-bdr rounded-14 shadow-shd2 fixed top-1/2 left-1/2 z-[var(--z-modal)] flex w-[min(460px,calc(100%-32px))] -translate-x-1/2 -translate-y-1/2 flex-col gap-3 border p-5 leading-[normal]", children: [_jsx(Dialog.Title, { className: "text-txt m-0 text-[length:var(--fs-drawer)] font-bold", children: title }), _jsx(Dialog.Description, { className: "text-body text-sub m-0 leading-[1.55]", children: description }), _jsx("div", { className: "mt-1 flex justify-end", children: _jsx(Dialog.Close, { asChild: true, children: _jsx(Button, { variant: "secondary", children: "Close" }) }) })] })] }) }));
|
|
15
|
-
}
|
|
16
|
-
/** The new batch AI job wizard. Until then, batches start from a list's bulk actions. */
|
|
17
|
-
export function NewBatchJob({ onClose }) {
|
|
18
|
-
return (_jsx(StandIn, { title: "New batch AI job", description: "Select posts or pages in their list, then pick Meta descriptions, Alt text or Summaries in the selection bar.", onClose: onClose, onFocusFallback: () => document.querySelector('[data-jobs-new]')?.focus() }));
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=placeholders.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"placeholders.js","sourceRoot":"","sources":["../../../src/views/Jobs/placeholders.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAGZ,OAAO,KAAK,MAAM,MAAM,wBAAwB,CAAA;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAA;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C;;;;GAIG;AAEH,SAAS,OAAO,CAAC,EACf,KAAK,EACL,WAAW,EACX,OAAO,EACP,eAAe,GAMhB;IACC,MAAM,WAAW,GAAG,cAAc,CAAC,eAAe,CAAC,CAAA;IACnD,OAAO,CACL,KAAC,MAAM,CAAC,IAAI,IAAC,IAAI,QAAC,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,YACtE,MAAC,MAAM,CAAC,MAAM,IAAC,SAAS,EAAE,oBAAoB,EAAE,aAC9C,KAAC,MAAM,CAAC,OAAO,IAAC,SAAS,EAAC,kDAAkD,GAAG,EAC/E,MAAC,MAAM,CAAC,OAAO,OACT,WAAW,EACf,SAAS,EAAC,sMAAsM,aAEhN,KAAC,MAAM,CAAC,KAAK,IAAC,SAAS,EAAC,uDAAuD,YAC5E,KAAK,GACO,EACf,KAAC,MAAM,CAAC,WAAW,IAAC,SAAS,EAAC,uCAAuC,YAClE,WAAW,GACO,EACrB,cAAK,SAAS,EAAC,uBAAuB,YACpC,KAAC,MAAM,CAAC,KAAK,IAAC,OAAO,kBACnB,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,sBAAe,GAC7B,GACX,IACS,IACH,GACJ,CACf,CAAA;AACH,CAAC;AAMD,yFAAyF;AACzF,MAAM,UAAU,WAAW,CAAC,EAAE,OAAO,EAAoB;IACvD,OAAO,CACL,KAAC,OAAO,IACN,KAAK,EAAC,kBAAkB,EACxB,WAAW,EAAC,+GAA+G,EAC3H,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAc,iBAAiB,CAAC,EAAE,KAAK,EAAE,GACtF,CACH,CAAA;AACH,CAAC"}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import type { ReactNode } from 'react'
|
|
4
|
-
import * as Dialog from '@radix-ui/react-dialog'
|
|
5
|
-
import { Button } from '../../components/ui/Button.js'
|
|
6
|
-
import { adminPortalContainer } from '../../lib/portal-container.js'
|
|
7
|
-
import { useReturnFocus } from './focus.js'
|
|
8
|
-
|
|
9
|
-
/*
|
|
10
|
-
* Stand-in until the batch wizard (P-20, jobs-new.jsx) is built. The list
|
|
11
|
-
* already opens it with the props the kit passes, so it's swapped by
|
|
12
|
-
* replacing the component here.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
function StandIn({
|
|
16
|
-
title,
|
|
17
|
-
description,
|
|
18
|
-
onClose,
|
|
19
|
-
onFocusFallback,
|
|
20
|
-
}: {
|
|
21
|
-
title: string
|
|
22
|
-
description: ReactNode
|
|
23
|
-
onClose: () => void
|
|
24
|
-
onFocusFallback: () => void
|
|
25
|
-
}) {
|
|
26
|
-
const returnFocus = useReturnFocus(onFocusFallback)
|
|
27
|
-
return (
|
|
28
|
-
<Dialog.Root open onOpenChange={(open) => (open ? undefined : onClose())}>
|
|
29
|
-
<Dialog.Portal container={adminPortalContainer()}>
|
|
30
|
-
<Dialog.Overlay className="bg-scrim-drawer fixed inset-0 z-[var(--z-modal)]" />
|
|
31
|
-
<Dialog.Content
|
|
32
|
-
{...returnFocus}
|
|
33
|
-
className="bg-card border-bdr rounded-14 shadow-shd2 fixed top-1/2 left-1/2 z-[var(--z-modal)] flex w-[min(460px,calc(100%-32px))] -translate-x-1/2 -translate-y-1/2 flex-col gap-3 border p-5 leading-[normal]"
|
|
34
|
-
>
|
|
35
|
-
<Dialog.Title className="text-txt m-0 text-[length:var(--fs-drawer)] font-bold">
|
|
36
|
-
{title}
|
|
37
|
-
</Dialog.Title>
|
|
38
|
-
<Dialog.Description className="text-body text-sub m-0 leading-[1.55]">
|
|
39
|
-
{description}
|
|
40
|
-
</Dialog.Description>
|
|
41
|
-
<div className="mt-1 flex justify-end">
|
|
42
|
-
<Dialog.Close asChild>
|
|
43
|
-
<Button variant="secondary">Close</Button>
|
|
44
|
-
</Dialog.Close>
|
|
45
|
-
</div>
|
|
46
|
-
</Dialog.Content>
|
|
47
|
-
</Dialog.Portal>
|
|
48
|
-
</Dialog.Root>
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface NewBatchJobProps {
|
|
53
|
-
onClose: () => void
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** The new batch AI job wizard. Until then, batches start from a list's bulk actions. */
|
|
57
|
-
export function NewBatchJob({ onClose }: NewBatchJobProps) {
|
|
58
|
-
return (
|
|
59
|
-
<StandIn
|
|
60
|
-
title="New batch AI job"
|
|
61
|
-
description="Select posts or pages in their list, then pick Meta descriptions, Alt text or Summaries in the selection bar."
|
|
62
|
-
onClose={onClose}
|
|
63
|
-
onFocusFallback={() => document.querySelector<HTMLElement>('[data-jobs-new]')?.focus()}
|
|
64
|
-
/>
|
|
65
|
-
)
|
|
66
|
-
}
|