@ossy/package-catalog 1.0.1
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/package.json +33 -0
- package/src/ActionCapabilityCard.jsx +87 -0
- package/src/ActionExamplesPanel.jsx +47 -0
- package/src/CatalogPageStyles.jsx +15 -0
- package/src/Definition.js +9 -0
- package/src/HowToCard.jsx +79 -0
- package/src/ManifestSection.jsx +259 -0
- package/src/PackageActionsSection.jsx +52 -0
- package/src/PackageHero.jsx +97 -0
- package/src/PackageHowToSection.jsx +99 -0
- package/src/PackageServiceToggle.jsx +69 -0
- package/src/PackagesBrowser.jsx +294 -0
- package/src/WidgetCapabilityCard.jsx +28 -0
- package/src/en.translations.json +85 -0
- package/src/formatPaths.js +69 -0
- package/src/index.js +9 -0
- package/src/package-detail.page.jsx +197 -0
- package/src/packageCopy.js +194 -0
- package/src/packageDetailSections.js +17 -0
- package/src/packageStoreStyles.js +305 -0
- package/src/packages.page.jsx +15 -0
- package/src/sv.translations.json +85 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Icon, Page, ContentHeader, Text, View } from '@ossy/design-system'
|
|
3
|
+
import { useApp } from '@ossy/app/shell'
|
|
4
|
+
import { useRouter } from '@ossy/router-react'
|
|
5
|
+
import { countPackageCapabilities } from './formatPaths.js'
|
|
6
|
+
import { ManifestSection } from './ManifestSection.jsx'
|
|
7
|
+
import { PackageHero } from './PackageHero.jsx'
|
|
8
|
+
import {
|
|
9
|
+
enrichActionWithSchema,
|
|
10
|
+
capabilitySchemaMapFromApp,
|
|
11
|
+
} from './ActionCapabilityCard.jsx'
|
|
12
|
+
import { PackageActionsSection } from './PackageActionsSection.jsx'
|
|
13
|
+
import { PackageHowToSection } from './PackageHowToSection.jsx'
|
|
14
|
+
import { PKG_DETAIL_SECTION_IDS } from './packageDetailSections.js'
|
|
15
|
+
import { PackageServiceToggle } from './PackageServiceToggle.jsx'
|
|
16
|
+
import { WidgetCapabilityCard } from './WidgetCapabilityCard.jsx'
|
|
17
|
+
import { pkgStoreEnvelopedSurfaceProps } from './packageStoreStyles.js'
|
|
18
|
+
import { CatalogPageStyles } from './CatalogPageStyles.jsx'
|
|
19
|
+
import {
|
|
20
|
+
filterBackgroundTasks,
|
|
21
|
+
getPackageIcon,
|
|
22
|
+
getPackagePitch,
|
|
23
|
+
slugToDisplayName,
|
|
24
|
+
} from './packageCopy.js'
|
|
25
|
+
|
|
26
|
+
export const metadata = {
|
|
27
|
+
id: 'packages/detail',
|
|
28
|
+
title: 'Capability overview',
|
|
29
|
+
path: {
|
|
30
|
+
en: '/packages/:packageSlug',
|
|
31
|
+
sv: '/paket/:packageSlug',
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default function PackageDetailPage () {
|
|
36
|
+
const app = useApp()
|
|
37
|
+
const router = useRouter()
|
|
38
|
+
const slug = router.params.packageSlug
|
|
39
|
+
const pkg = app?.manifestSummary?.packages?.find((p) => p.slug === slug)
|
|
40
|
+
|
|
41
|
+
if (!pkg) {
|
|
42
|
+
return (
|
|
43
|
+
<Page maxWidth="l" gap="m" className="pkg-store-root">
|
|
44
|
+
<Text variant="heading-secondary" as="h2" text="package-catalog.detail.notFound.title" />
|
|
45
|
+
<Text text="package-catalog.detail.notFound.body" params={{ slug: slug || '—' }} />
|
|
46
|
+
</Page>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const displayName = slugToDisplayName(pkg.slug)
|
|
51
|
+
const pitch = getPackagePitch(pkg)
|
|
52
|
+
const packageIcon = getPackageIcon(pkg)
|
|
53
|
+
const packageDefinition = app?.manifestSummary?.definitions?.[pkg.slug]
|
|
54
|
+
const totalCapabilities = countPackageCapabilities(pkg)
|
|
55
|
+
const backgroundTasks = filterBackgroundTasks(pkg.tasks)
|
|
56
|
+
|
|
57
|
+
const capabilitySchemas = capabilitySchemaMapFromApp(app?.capabilities)
|
|
58
|
+
|
|
59
|
+
const documentedActions = (pkg.actions || []).map((action) =>
|
|
60
|
+
enrichActionWithSchema(action, capabilitySchemas),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
const manifestSectionProps = {
|
|
64
|
+
titleVariant: 'heading-tertiary',
|
|
65
|
+
compact: true,
|
|
66
|
+
enveloped: true,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<>
|
|
71
|
+
<CatalogPageStyles />
|
|
72
|
+
|
|
73
|
+
<Page maxWidth="xl" gap="l" className="pkg-store-root">
|
|
74
|
+
<PackageHero
|
|
75
|
+
eyebrow={pkg.package}
|
|
76
|
+
title={displayName}
|
|
77
|
+
text={pitch}
|
|
78
|
+
meta="package-catalog.detail.meta.capabilities"
|
|
79
|
+
metaParams={{
|
|
80
|
+
count: totalCapabilities,
|
|
81
|
+
countSuffix: totalCapabilities === 1 ? 'y' : 'ies',
|
|
82
|
+
}}
|
|
83
|
+
maxWidth="l"
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
<ContentHeader
|
|
87
|
+
inset="none"
|
|
88
|
+
title={displayName}
|
|
89
|
+
descriptionMaxWidth="m"
|
|
90
|
+
lead={<Text maxWidth="m">{pitch}</Text>}
|
|
91
|
+
far={(
|
|
92
|
+
<PackageServiceToggle
|
|
93
|
+
packageName={pkg.package}
|
|
94
|
+
entitlementRequired={packageDefinition?.entitlementRequired}
|
|
95
|
+
/>
|
|
96
|
+
)}
|
|
97
|
+
/>
|
|
98
|
+
|
|
99
|
+
<PackageHowToSection pkg={pkg} backgroundTasks={backgroundTasks} />
|
|
100
|
+
|
|
101
|
+
{pkg.components?.length > 0 && (
|
|
102
|
+
<View id={PKG_DETAIL_SECTION_IDS.widgets} {...pkgStoreEnvelopedSurfaceProps}>
|
|
103
|
+
<View gap="xs">
|
|
104
|
+
<View layout="row" gap="s" alignItems="center">
|
|
105
|
+
<Icon name="layout-grid" size="m" />
|
|
106
|
+
<Text as="h2" variant="heading-secondary" text="package-catalog.detail.section.widgets.title" />
|
|
107
|
+
</View>
|
|
108
|
+
<Text
|
|
109
|
+
text="package-catalog.detail.section.widgets.subtitle"
|
|
110
|
+
className="pkg-store-prose--narrow"
|
|
111
|
+
/>
|
|
112
|
+
</View>
|
|
113
|
+
<View gap="m" layout="row-wrap">
|
|
114
|
+
{pkg.components.map((component) => (
|
|
115
|
+
<WidgetCapabilityCard key={component.id} component={component} icon={packageIcon} />
|
|
116
|
+
))}
|
|
117
|
+
</View>
|
|
118
|
+
</View>
|
|
119
|
+
)}
|
|
120
|
+
|
|
121
|
+
{documentedActions.length > 0 && (
|
|
122
|
+
<PackageActionsSection far={documentedActions} />
|
|
123
|
+
)}
|
|
124
|
+
|
|
125
|
+
{backgroundTasks.length > 0 && (
|
|
126
|
+
<ManifestSection
|
|
127
|
+
sectionId={PKG_DETAIL_SECTION_IDS.tasks}
|
|
128
|
+
title="package-catalog.detail.section.tasks.title"
|
|
129
|
+
subtitle="package-catalog.detail.section.tasks.subtitle"
|
|
130
|
+
items={backgroundTasks}
|
|
131
|
+
variant="backgroundTasks"
|
|
132
|
+
icon="timer"
|
|
133
|
+
enveloped
|
|
134
|
+
{...manifestSectionProps}
|
|
135
|
+
/>
|
|
136
|
+
)}
|
|
137
|
+
|
|
138
|
+
<ManifestSection
|
|
139
|
+
sectionId={PKG_DETAIL_SECTION_IDS.aggregates}
|
|
140
|
+
title="package-catalog.detail.section.aggregates.title"
|
|
141
|
+
subtitle="package-catalog.detail.section.aggregates.subtitle"
|
|
142
|
+
items={pkg.aggregates}
|
|
143
|
+
variant="entities"
|
|
144
|
+
icon="stack"
|
|
145
|
+
enveloped
|
|
146
|
+
{...manifestSectionProps}
|
|
147
|
+
/>
|
|
148
|
+
|
|
149
|
+
<ManifestSection
|
|
150
|
+
title="package-catalog.detail.section.pages.title"
|
|
151
|
+
subtitle="package-catalog.detail.section.pages.subtitle"
|
|
152
|
+
items={pkg.pages}
|
|
153
|
+
variant="pages"
|
|
154
|
+
linkPages
|
|
155
|
+
icon="file-document"
|
|
156
|
+
{...manifestSectionProps}
|
|
157
|
+
/>
|
|
158
|
+
|
|
159
|
+
<ManifestSection
|
|
160
|
+
title="package-catalog.detail.section.resources.title"
|
|
161
|
+
subtitle="package-catalog.detail.section.resources.subtitle"
|
|
162
|
+
items={pkg.schemas}
|
|
163
|
+
variant="entities"
|
|
164
|
+
icon="database"
|
|
165
|
+
{...manifestSectionProps}
|
|
166
|
+
/>
|
|
167
|
+
|
|
168
|
+
<ManifestSection
|
|
169
|
+
title="package-catalog.detail.section.apis.title"
|
|
170
|
+
subtitle="package-catalog.detail.section.apis.subtitle"
|
|
171
|
+
items={pkg.apis}
|
|
172
|
+
variant="secondary"
|
|
173
|
+
icon="code"
|
|
174
|
+
{...manifestSectionProps}
|
|
175
|
+
/>
|
|
176
|
+
|
|
177
|
+
<ManifestSection
|
|
178
|
+
title="package-catalog.detail.section.integrations.title"
|
|
179
|
+
subtitle="package-catalog.detail.section.integrations.subtitle"
|
|
180
|
+
items={pkg.integrations}
|
|
181
|
+
variant="entities"
|
|
182
|
+
icon="link"
|
|
183
|
+
{...manifestSectionProps}
|
|
184
|
+
/>
|
|
185
|
+
|
|
186
|
+
<ManifestSection
|
|
187
|
+
title="package-catalog.detail.section.emails.title"
|
|
188
|
+
subtitle="package-catalog.detail.section.emails.subtitle"
|
|
189
|
+
items={pkg.emails}
|
|
190
|
+
variant="secondary"
|
|
191
|
+
icon="email"
|
|
192
|
+
{...manifestSectionProps}
|
|
193
|
+
/>
|
|
194
|
+
</Page>
|
|
195
|
+
</>
|
|
196
|
+
)
|
|
197
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/** @type {Record<string, string>} */
|
|
2
|
+
const ICON_BY_SLUG = {
|
|
3
|
+
analytics: 'chart',
|
|
4
|
+
apps: 'layout-grid',
|
|
5
|
+
authentication: 'keyhole',
|
|
6
|
+
automation: 'attribution',
|
|
7
|
+
booking: 'calendar',
|
|
8
|
+
calendar: 'calendar',
|
|
9
|
+
consulting: 'briefcase',
|
|
10
|
+
consultancy: 'briefcase',
|
|
11
|
+
contracts: 'file-document',
|
|
12
|
+
distribution: 'share',
|
|
13
|
+
domains: 'globe',
|
|
14
|
+
email: 'email',
|
|
15
|
+
employees: 'users',
|
|
16
|
+
forecasts: 'chart',
|
|
17
|
+
gmail: 'email',
|
|
18
|
+
home: 'home',
|
|
19
|
+
'integration-stripe': 'credit-card',
|
|
20
|
+
'media-tasks': 'image',
|
|
21
|
+
observability: 'activity',
|
|
22
|
+
pages: 'file-document',
|
|
23
|
+
policies: 'shield',
|
|
24
|
+
profile: 'user',
|
|
25
|
+
resources: 'database',
|
|
26
|
+
resumes: 'file-document',
|
|
27
|
+
storage: 'software-upload',
|
|
28
|
+
tasks: 'check-circle',
|
|
29
|
+
themes: 'palette',
|
|
30
|
+
timesheets: 'clock',
|
|
31
|
+
tokens: 'palette',
|
|
32
|
+
tools: 'wrench',
|
|
33
|
+
users: 'users',
|
|
34
|
+
web: 'globe',
|
|
35
|
+
workspaces: 'building',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** @type {Record<string, string>} */
|
|
39
|
+
const PITCH_BY_SLUG = {
|
|
40
|
+
'app-test': 'Interactive demo shell for exploring Ossy feature packages',
|
|
41
|
+
analytics: 'Product analytics and usage insights',
|
|
42
|
+
apps: 'Multi-app workspace management',
|
|
43
|
+
authentication: 'Sign-in, sessions, and account security',
|
|
44
|
+
automation: 'Workflow automation and triggers',
|
|
45
|
+
booking: 'Booking & scheduling for service providers',
|
|
46
|
+
calendar: 'Calendars, availability, and time slots',
|
|
47
|
+
consulting: 'Consulting profiles and client-facing pages',
|
|
48
|
+
consultancy: 'Consultancy operations and delivery',
|
|
49
|
+
contracts: 'Contracts and agreement workflows',
|
|
50
|
+
distribution: 'Content distribution and publishing',
|
|
51
|
+
domains: 'Custom domains and DNS',
|
|
52
|
+
email: 'Transactional email and templates',
|
|
53
|
+
employees: 'Team members and org structure',
|
|
54
|
+
forecasts: 'Revenue and capacity forecasting',
|
|
55
|
+
gmail: 'Gmail integration and inbox sync',
|
|
56
|
+
home: 'Workspace home and navigation',
|
|
57
|
+
'integration-stripe': 'Stripe payments and billing',
|
|
58
|
+
'media-tasks': 'Media processing background jobs',
|
|
59
|
+
observability: 'Logging, metrics, and diagnostics',
|
|
60
|
+
pages: 'Page builder and site structure',
|
|
61
|
+
policies: 'Policies, roles, and permissions',
|
|
62
|
+
profile: 'User profiles and public identity',
|
|
63
|
+
resources: 'Structured resources and content types',
|
|
64
|
+
resumes: 'Résumés and professional portfolios',
|
|
65
|
+
storage: 'Files, folders, and workspace storage',
|
|
66
|
+
tasks: 'Tasks, checklists, and async work',
|
|
67
|
+
themes: 'Themes, branding, and appearance',
|
|
68
|
+
timesheets: 'Time tracking and billable hours',
|
|
69
|
+
tokens: 'Design tokens and theme variables',
|
|
70
|
+
tools: 'Developer tools and utilities',
|
|
71
|
+
users: 'Users, accounts, and membership',
|
|
72
|
+
web: 'Public web surfaces and marketing',
|
|
73
|
+
workspaces: 'Workspaces, teams, and tenancy',
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {string} slug
|
|
78
|
+
* @returns {string}
|
|
79
|
+
*/
|
|
80
|
+
export function slugToDisplayName (slug) {
|
|
81
|
+
if (!slug) return 'Package'
|
|
82
|
+
return slug
|
|
83
|
+
.split('-')
|
|
84
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
85
|
+
.join(' ')
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @param {{ slug?: string }} pkg
|
|
90
|
+
* @returns {string}
|
|
91
|
+
*/
|
|
92
|
+
export function getPackageIcon (pkg) {
|
|
93
|
+
const slug = pkg?.slug
|
|
94
|
+
if (slug && ICON_BY_SLUG[slug]) return ICON_BY_SLUG[slug]
|
|
95
|
+
const highlights = getPackageHighlights(pkg)
|
|
96
|
+
return highlights[0]?.icon || 'package'
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {{ slug?: string, package?: string }} pkg
|
|
101
|
+
* @returns {string}
|
|
102
|
+
*/
|
|
103
|
+
export function getPackagePitch (pkg) {
|
|
104
|
+
const slug = pkg?.slug
|
|
105
|
+
if (slug && PITCH_BY_SLUG[slug]) return PITCH_BY_SLUG[slug]
|
|
106
|
+
const name = slugToDisplayName(slug || '')
|
|
107
|
+
return `${name} — Ossy feature package`
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Known background task descriptions for package detail showcase. */
|
|
111
|
+
export const SHOWCASE_TASK_DESCRIPTIONS = {
|
|
112
|
+
'@ossy/booking/tasks/send-reminder': 'Hourly cron — emails clients ~24h before their booking.',
|
|
113
|
+
'@ossy/workspaces/tasks/sync-workspace-membership': 'Event-driven — syncs membership when workspace users change.',
|
|
114
|
+
'@ossy/media-tasks/tasks/resize-common-web': 'On image upload — generates thumbnails and gallery sizes.',
|
|
115
|
+
'@ossy/media-tasks/tasks/visual-content-descriptors': 'On image upload — extracts visual descriptors for search.',
|
|
116
|
+
'@ossy/event-store/tasks/aggregate-rebuild': 'Rebuilds aggregate projections from the event stream.',
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Primary invoke tasks use `{feature}/tasks/{intent}` derived from `{feature}/actions/{intent}`; background tasks use other names under `…/tasks/…`.
|
|
121
|
+
*
|
|
122
|
+
* @param {string} id
|
|
123
|
+
* @returns {boolean}
|
|
124
|
+
*/
|
|
125
|
+
export function isBackgroundTaskId (id) {
|
|
126
|
+
return typeof id === 'string' && id.includes('/tasks/')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {Array<{ id: string, title?: string, description?: string }> | undefined} tasks
|
|
131
|
+
* @returns {Array<{ id: string, title?: string, description?: string }>}
|
|
132
|
+
*/
|
|
133
|
+
export function filterBackgroundTasks (tasks) {
|
|
134
|
+
return (tasks || []).filter((task) => isBackgroundTaskId(task.id))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @param {{ id: string, title?: string, description?: string }} task
|
|
139
|
+
* @returns {string}
|
|
140
|
+
*/
|
|
141
|
+
export function getTaskDisplayTitle (task) {
|
|
142
|
+
if (task.title) return task.title
|
|
143
|
+
const segment = task.id.split('/tasks/').pop()
|
|
144
|
+
return humanizeCapabilityId(segment || task.id)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @param {{ id: string, description?: string }} task
|
|
149
|
+
* @returns {string | undefined}
|
|
150
|
+
*/
|
|
151
|
+
export function getTaskDisplayDescription (task) {
|
|
152
|
+
return task.description || SHOWCASE_TASK_DESCRIPTIONS[task.id]
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @param {string} id
|
|
157
|
+
* @returns {string}
|
|
158
|
+
*/
|
|
159
|
+
export function humanizeCapabilityId (id) {
|
|
160
|
+
if (!id) return ''
|
|
161
|
+
const segment = id.includes('/') ? id.split('/').pop() : id
|
|
162
|
+
return segment
|
|
163
|
+
.replace(/[-_]/g, ' ')
|
|
164
|
+
.replace(/\b\w/g, (c) => c.toUpperCase())
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @param {object} pkg
|
|
169
|
+
* @returns {{ key: string, label: string, count: number, icon: string }[]}
|
|
170
|
+
*/
|
|
171
|
+
export function getPackageHighlights (pkg) {
|
|
172
|
+
const rows = [
|
|
173
|
+
{ key: 'pages', label: 'Pages', count: pkg.pages?.length || 0, icon: 'file-document' },
|
|
174
|
+
{ key: 'actions', label: 'Actions', count: pkg.actions?.length || 0, icon: 'bolt' },
|
|
175
|
+
{
|
|
176
|
+
key: 'schemas',
|
|
177
|
+
label: 'Resource types',
|
|
178
|
+
count: pkg.schemas?.length || 0,
|
|
179
|
+
icon: 'database',
|
|
180
|
+
},
|
|
181
|
+
{ key: 'apis', label: 'APIs', count: pkg.apis?.length || 0, icon: 'code' },
|
|
182
|
+
{ key: 'components', label: 'Components', count: pkg.components?.length || 0, icon: 'layout-grid' },
|
|
183
|
+
{ key: 'tasks', label: 'Tasks', count: pkg.tasks?.length || 0, icon: 'check-circle' },
|
|
184
|
+
{
|
|
185
|
+
key: 'integrations',
|
|
186
|
+
label: 'Integrations',
|
|
187
|
+
count: pkg.integrations?.length || 0,
|
|
188
|
+
icon: 'link',
|
|
189
|
+
},
|
|
190
|
+
{ key: 'emails', label: 'Emails', count: pkg.emails?.length || 0, icon: 'email' },
|
|
191
|
+
{ key: 'aggregates', label: 'Aggregates', count: pkg.aggregates?.length || 0, icon: 'stack' },
|
|
192
|
+
]
|
|
193
|
+
return rows.filter((r) => r.count > 0)
|
|
194
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Stable anchor ids for package detail capability sections. */
|
|
2
|
+
export const PKG_DETAIL_SECTION_IDS = {
|
|
3
|
+
widgets: 'pkg-section-widgets',
|
|
4
|
+
actions: 'pkg-section-actions',
|
|
5
|
+
tasks: 'pkg-section-tasks',
|
|
6
|
+
aggregates: 'pkg-section-aggregates',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} sectionId
|
|
11
|
+
*/
|
|
12
|
+
export function scrollToPackageSection (sectionId) {
|
|
13
|
+
const el = document.getElementById(sectionId)
|
|
14
|
+
if (!el) return
|
|
15
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
16
|
+
window.history.replaceState(null, '', `#${sectionId}`)
|
|
17
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/** Enveloping surface wrapper shared by How-to, Actions, tasks, and aggregates sections. */
|
|
2
|
+
export const pkgStoreEnvelopedSurfaceProps = {
|
|
3
|
+
gap: 'm',
|
|
4
|
+
roundness: 'm',
|
|
5
|
+
inset: 'l',
|
|
6
|
+
className: 'pkg-store-envelope',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Shared storefront styles for package list and detail pages. */
|
|
10
|
+
export const packageStoreStyles = `
|
|
11
|
+
.pkg-store-root {
|
|
12
|
+
height: 100%;
|
|
13
|
+
overflow-y: auto;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.pkg-store-scroll-panel {
|
|
17
|
+
padding: var(--space-m) var(--space-l);
|
|
18
|
+
height: 100%;
|
|
19
|
+
overflow-y: auto;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.pkg-store-envelope {
|
|
23
|
+
border: 1px solid var(--separator-primary);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.pkg-store-prose {
|
|
27
|
+
max-width: 640px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.pkg-store-prose--muted {
|
|
31
|
+
max-width: 640px;
|
|
32
|
+
opacity: 0.85;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.pkg-store-prose--narrow {
|
|
36
|
+
max-width: 560px;
|
|
37
|
+
opacity: 0.75;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.pkg-store-text-strong {
|
|
41
|
+
font-weight: 600;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.pkg-store-text-bold {
|
|
45
|
+
font-weight: 700;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.pkg-store-text-center {
|
|
49
|
+
text-align: center;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.pkg-store-text-muted {
|
|
53
|
+
opacity: 0.8;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.pkg-store-text-dim {
|
|
57
|
+
opacity: 0.85;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.pkg-store-mono {
|
|
61
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
62
|
+
font-size: 0.8125rem;
|
|
63
|
+
line-height: 1.4;
|
|
64
|
+
word-break: break-all;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.pkg-store-mono--sm {
|
|
68
|
+
font-size: 0.75rem;
|
|
69
|
+
word-break: break-word;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.pkg-store-mono--xs {
|
|
73
|
+
font-size: 0.7rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.pkg-store-card {
|
|
77
|
+
border: 1px solid var(--separator-primary);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.pkg-store-howto-card {
|
|
81
|
+
min-width: 280px;
|
|
82
|
+
flex: 1 1 280px;
|
|
83
|
+
max-width: 360px;
|
|
84
|
+
min-height: 160px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.pkg-store-howto-card--link {
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.pkg-store-widget-card {
|
|
92
|
+
min-width: 280px;
|
|
93
|
+
flex: 1 1 280px;
|
|
94
|
+
max-width: 360px;
|
|
95
|
+
min-height: 140px;
|
|
96
|
+
border: 1px solid var(--separator-primary);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.pkg-store-action-card {
|
|
100
|
+
min-width: 200px;
|
|
101
|
+
flex: 1 1 200px;
|
|
102
|
+
max-width: 280px;
|
|
103
|
+
border: 1px solid var(--separator-primary);
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
text-align: left;
|
|
106
|
+
overflow: visible;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.pkg-store-action-card[aria-pressed="true"] {
|
|
110
|
+
border-color: color-mix(in srgb, var(--foreground) 28%, var(--separator-primary));
|
|
111
|
+
background: color-mix(in srgb, var(--foreground) 4%, var(--surface-primary));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.pkg-store-action-examples {
|
|
115
|
+
border: 1px solid var(--separator-primary);
|
|
116
|
+
min-width: 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.pkg-store-package-link {
|
|
120
|
+
width: 200px;
|
|
121
|
+
border: 1px solid var(--separator-primary);
|
|
122
|
+
text-decoration: none;
|
|
123
|
+
color: inherit;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.pkg-store-section-link {
|
|
127
|
+
align-self: center;
|
|
128
|
+
opacity: 0.65;
|
|
129
|
+
font-size: 0.8125rem;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.pkg-store-hero-cover {
|
|
133
|
+
height: 100%;
|
|
134
|
+
border-radius: var(--space-m);
|
|
135
|
+
padding: var(--space-xl) var(--space-s);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.pkg-store-hero-eyebrow {
|
|
139
|
+
opacity: 0.75;
|
|
140
|
+
text-transform: uppercase;
|
|
141
|
+
letter-spacing: 0.06em;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.pkg-store-hero-title {
|
|
145
|
+
text-wrap: balance;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.pkg-store-hero-subtitle {
|
|
149
|
+
max-width: 800px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.pkg-store-hero-meta {
|
|
153
|
+
opacity: 0.65;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.pkg-store-hero-actions {
|
|
157
|
+
flex-wrap: wrap;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.pkg-store-search {
|
|
161
|
+
width: 100%;
|
|
162
|
+
max-width: 420px;
|
|
163
|
+
margin: 0 auto;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.pkg-store-search [data-component="input"] {
|
|
167
|
+
width: 100%;
|
|
168
|
+
border-radius: var(--space-s);
|
|
169
|
+
padding: var(--space-s) var(--space-m);
|
|
170
|
+
font-size: 1rem;
|
|
171
|
+
line-height: 1.4;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.pkg-store-grid-meta {
|
|
175
|
+
opacity: 0.72;
|
|
176
|
+
font-size: 0.9375rem;
|
|
177
|
+
color: var(--text-default-color, var(--foreground));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.pkg-store-pages-grid {
|
|
181
|
+
display: grid;
|
|
182
|
+
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
183
|
+
gap: var(--space-s);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.pkg-store-pages-list {
|
|
187
|
+
display: flex;
|
|
188
|
+
flex-direction: column;
|
|
189
|
+
gap: var(--space-s);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.pkg-store-page-row [data-button] {
|
|
193
|
+
padding: var(--space-xs);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.pkg-store-actions-split {
|
|
197
|
+
display: grid;
|
|
198
|
+
grid-template-columns: minmax(200px, 1fr) minmax(280px, 1.2fr);
|
|
199
|
+
gap: var(--space-m);
|
|
200
|
+
align-items: start;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.pkg-store-actions-list {
|
|
204
|
+
min-width: 0;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.pkg-store-action-card:focus-visible {
|
|
208
|
+
outline: 2px solid color-mix(in srgb, var(--foreground) 35%, transparent);
|
|
209
|
+
outline-offset: 2px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@media (max-width: 720px) {
|
|
213
|
+
.pkg-store-actions-split {
|
|
214
|
+
grid-template-columns: 1fr;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.pkg-store-entity {
|
|
219
|
+
border: 1px solid var(--separator-primary);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.pkg-store-entities-grid,
|
|
223
|
+
.pkg-store-secondary-grid {
|
|
224
|
+
display: grid;
|
|
225
|
+
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
|
226
|
+
gap: var(--space-s);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.pkg-store-secondary-item {
|
|
230
|
+
border: 1px solid var(--separator-primary);
|
|
231
|
+
background: color-mix(in srgb, var(--foreground) 4%, var(--surface-primary));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.pkg-store-footer {
|
|
235
|
+
padding: var(--space-l) var(--space-m);
|
|
236
|
+
border-radius: var(--space-m);
|
|
237
|
+
border: 1px solid var(--separator-primary);
|
|
238
|
+
background: color-mix(in srgb, var(--foreground) 4%, var(--surface-primary));
|
|
239
|
+
text-align: center;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.pkg-store-howto-card,
|
|
243
|
+
.pkg-store-action-card,
|
|
244
|
+
.pkg-store-widget-card {
|
|
245
|
+
overflow: visible;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.pkg-store-howto-card--link {
|
|
249
|
+
transition: border-color 0.15s ease, background 0.15s ease;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.pkg-store-howto-card--link:hover,
|
|
253
|
+
.pkg-store-howto-card--link:focus-visible {
|
|
254
|
+
border-color: color-mix(in srgb, var(--foreground) 22%, var(--separator-primary));
|
|
255
|
+
background: color-mix(in srgb, var(--foreground) 3%, var(--surface-primary));
|
|
256
|
+
outline: none;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
#pkg-section-widgets,
|
|
260
|
+
#pkg-section-actions,
|
|
261
|
+
#pkg-section-tasks,
|
|
262
|
+
#pkg-section-aggregates {
|
|
263
|
+
scroll-margin-top: var(--space-l);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.pkg-store-card-body,
|
|
267
|
+
.pkg-store-action-card [data-component="text"] {
|
|
268
|
+
overflow-wrap: anywhere;
|
|
269
|
+
word-break: break-word;
|
|
270
|
+
white-space: normal;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.pkg-store-search--inline {
|
|
274
|
+
width: 100%;
|
|
275
|
+
max-width: 100%;
|
|
276
|
+
margin: 0;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.pkg-store-search--inline [data-component="input"] {
|
|
280
|
+
width: 100%;
|
|
281
|
+
border-radius: var(--space-s);
|
|
282
|
+
padding: var(--space-s) var(--space-m);
|
|
283
|
+
font-size: 1rem;
|
|
284
|
+
line-height: 1.4;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
[data-component="@ossy/package-catalog/package-hero"] {
|
|
288
|
+
gap: var(--space-m);
|
|
289
|
+
min-height: min(42vh, 420px);
|
|
290
|
+
height: auto;
|
|
291
|
+
background-attachment: scroll;
|
|
292
|
+
box-shadow: inset 0 1px 0 color-mix(in srgb, var(--foreground) 6%, transparent);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
[data-rounded] {
|
|
296
|
+
border-radius: var(--space-m);
|
|
297
|
+
overflow: hidden;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@media (min-width: 900px) {
|
|
301
|
+
[data-component="@ossy/package-catalog/package-hero"] {
|
|
302
|
+
min-height: min(46vh, 520px);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
`
|