@ossy/app 3.25.0 → 3.27.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/cli/manifest-plugin.js +15 -5
- package/package.json +16 -16
- package/src/shell/App.jsx +9 -1
- package/src/shell/DevPagesPanel.jsx +7 -12
- package/src/shell/MobileShellNav.jsx +2 -2
- package/src/shell/ThemeEditor.jsx +27 -15
- package/src/shell/buildSidebarNav.js +1 -1
- package/src/shell/resolvePackageHomePageId.js +6 -5
- package/src/shell/themeEditorStyles.js +27 -3
package/cli/manifest-plugin.js
CHANGED
|
@@ -73,7 +73,8 @@ import {
|
|
|
73
73
|
* @typedef {object} IntegrationManifestEntry
|
|
74
74
|
* @property {string} id Unique integration slug (e.g. `'email'`).
|
|
75
75
|
* @property {string} entry URL the platform serves the integration bundle from.
|
|
76
|
-
* @property {string[]} credentials Env var names required by
|
|
76
|
+
* @property {string[]} credentials Env var names required by a platform integration.
|
|
77
|
+
* @property {string[]} [secrets] Secret key names for a workspace integration.
|
|
77
78
|
*
|
|
78
79
|
* @typedef {object} StartupManifestEntry
|
|
79
80
|
* @property {string} id Unique startup slug (e.g. `'create-bot-user'`).
|
|
@@ -257,15 +258,18 @@ export function manifestPlugin ({ entriesByStub, srcDir, staticOutDir, configVal
|
|
|
257
258
|
// produce routable entries; they accumulate into a separate array.
|
|
258
259
|
if (entryInfo.kind === 'integration') {
|
|
259
260
|
const integrationId = mod && mod.id
|
|
260
|
-
const credentials = mod
|
|
261
|
+
const credentials = Array.isArray(mod?.credentials) ? mod.credentials : null
|
|
262
|
+
const secrets = Array.isArray(mod?.secrets)
|
|
263
|
+
? mod.secrets.filter((key) => typeof key === 'string' && key.trim())
|
|
264
|
+
: []
|
|
261
265
|
if (typeof integrationId !== 'string' || integrationId.trim() === '') {
|
|
262
266
|
this.error(
|
|
263
267
|
`[@ossy/app][build] integration entry ${entryInfo.sourcePath} must export a non-empty string "id"`,
|
|
264
268
|
)
|
|
265
269
|
}
|
|
266
|
-
if (!
|
|
270
|
+
if (!credentials && secrets.length === 0) {
|
|
267
271
|
this.error(
|
|
268
|
-
`[@ossy/app][build] integration entry ${entryInfo.sourcePath} must export a "credentials" array`,
|
|
272
|
+
`[@ossy/app][build] integration entry ${entryInfo.sourcePath} must export a "credentials" array or a "secrets" array`,
|
|
269
273
|
)
|
|
270
274
|
}
|
|
271
275
|
if (typeof mod.connect !== 'function') {
|
|
@@ -277,7 +281,13 @@ export function manifestPlugin ({ entriesByStub, srcDir, staticOutDir, configVal
|
|
|
277
281
|
this.error(`[@ossy/app][build] Duplicate integration id "${integrationId}"`)
|
|
278
282
|
}
|
|
279
283
|
seenIntegrationIds.add(integrationId)
|
|
280
|
-
integrations.push(withSourcePath({
|
|
284
|
+
integrations.push(withSourcePath({
|
|
285
|
+
id: integrationId,
|
|
286
|
+
entry: url,
|
|
287
|
+
credentials: credentials ?? [],
|
|
288
|
+
...(secrets.length ? { secrets } : {}),
|
|
289
|
+
package: entryPackage(entryInfo, appPackageName),
|
|
290
|
+
}, entryInfo, projectRoot))
|
|
281
291
|
continue
|
|
282
292
|
}
|
|
283
293
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/app",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.27.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -49,22 +49,22 @@
|
|
|
49
49
|
"@babel/eslint-parser": "^7.15.8",
|
|
50
50
|
"@babel/preset-react": "^7.26.3",
|
|
51
51
|
"@babel/register": "^7.25.9",
|
|
52
|
-
"@ossy/authentication": "^3.
|
|
53
|
-
"@ossy/design-system": "^3.
|
|
52
|
+
"@ossy/authentication": "^3.26.0",
|
|
53
|
+
"@ossy/design-system": "^3.27.0",
|
|
54
54
|
"@ossy/locale": "^3.4.0",
|
|
55
|
-
"@ossy/manifest": "^3.
|
|
56
|
-
"@ossy/package-catalog": "^3.
|
|
57
|
-
"@ossy/pages": "^3.0
|
|
58
|
-
"@ossy/platform": "^3.
|
|
59
|
-
"@ossy/resources": "^3.
|
|
55
|
+
"@ossy/manifest": "^3.27.0",
|
|
56
|
+
"@ossy/package-catalog": "^3.27.0",
|
|
57
|
+
"@ossy/pages": "^3.26.0",
|
|
58
|
+
"@ossy/platform": "^3.27.0",
|
|
59
|
+
"@ossy/resources": "^3.27.0",
|
|
60
60
|
"@ossy/router": "^3.25.0",
|
|
61
|
-
"@ossy/router-react": "^3.
|
|
62
|
-
"@ossy/schema": "^3.
|
|
63
|
-
"@ossy/sdk": "^3.
|
|
64
|
-
"@ossy/sdk-react": "^3.
|
|
65
|
-
"@ossy/themes": "^3.
|
|
66
|
-
"@ossy/users": "^3.
|
|
67
|
-
"@ossy/workspaces": "^3.
|
|
61
|
+
"@ossy/router-react": "^3.27.0",
|
|
62
|
+
"@ossy/schema": "^3.27.0",
|
|
63
|
+
"@ossy/sdk": "^3.26.0",
|
|
64
|
+
"@ossy/sdk-react": "^3.26.0",
|
|
65
|
+
"@ossy/themes": "^3.26.0",
|
|
66
|
+
"@ossy/users": "^3.27.0",
|
|
67
|
+
"@ossy/workspaces": "^3.27.0",
|
|
68
68
|
"@rollup/plugin-alias": "^6.0.0",
|
|
69
69
|
"@rollup/plugin-babel": "^7.1.0",
|
|
70
70
|
"@rollup/plugin-commonjs": "^29.0.0",
|
|
@@ -98,5 +98,5 @@
|
|
|
98
98
|
"README.md",
|
|
99
99
|
"tsconfig.json"
|
|
100
100
|
],
|
|
101
|
-
"gitHead": "
|
|
101
|
+
"gitHead": "f72042c42723468c010d0d9744ad69257143d0b9"
|
|
102
102
|
}
|
package/src/shell/App.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useEffect } from 'react'
|
|
2
2
|
import { SDK } from '@ossy/sdk'
|
|
3
3
|
import { WorkspaceProvider } from '@ossy/sdk-react'
|
|
4
4
|
import { Theme, ComponentSlotsProvider, LocaleProvider, DEFAULT_FORM_FIELD_SLOTS } from '@ossy/design-system'
|
|
@@ -13,6 +13,13 @@ import { Router } from '@ossy/router-react'
|
|
|
13
13
|
import { AppContext } from './AppContext.js'
|
|
14
14
|
import { UserSetupGuard } from './UserSetupGuard.jsx'
|
|
15
15
|
|
|
16
|
+
function MarkHydrated () {
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
document.documentElement.dataset.hydrated = 'true'
|
|
19
|
+
}, [])
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
export const App = ({ children, language, messages, fallbackMessages, sdk: sdkOverride, ..._appSettings }) => {
|
|
17
24
|
const appSettings = { ...defaultAppSettings(), ..._appSettings }
|
|
18
25
|
|
|
@@ -34,6 +41,7 @@ export const App = ({ children, language, messages, fallbackMessages, sdk: sdkOv
|
|
|
34
41
|
supportedLanguages={appSettings.supportedLanguages}
|
|
35
42
|
>
|
|
36
43
|
<AppContext.Provider value={contextSettings}>
|
|
44
|
+
<MarkHydrated />
|
|
37
45
|
<ComponentSlotsProvider slots={{ ...DEFAULT_FORM_FIELD_SLOTS, ...DEFAULT_SCHEMA_VIEW_SLOTS, ...DEFAULT_SCHEMA_FORM_SLOTS, ...(components || {}) }}>
|
|
38
46
|
<Theme theme={appSettings.theme} themes={appSettings.themes}>
|
|
39
47
|
<WorkspaceProvider
|
|
@@ -5,12 +5,7 @@ import { useApp } from './AppContext.js'
|
|
|
5
5
|
import { formatPagePaths, groupPagesByFeature } from './devPagesUtils.js'
|
|
6
6
|
import { packageNameToSlug } from '@ossy/manifest/build-manifest-summary'
|
|
7
7
|
|
|
8
|
-
const monoStyle = {
|
|
9
|
-
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
|
|
10
|
-
fontSize: '0.8125rem',
|
|
11
|
-
lineHeight: 1.4,
|
|
12
|
-
wordBreak: 'break-all',
|
|
13
|
-
}
|
|
8
|
+
const monoStyle = { wordBreak: 'break-all' }
|
|
14
9
|
|
|
15
10
|
const currentPageStyles = {
|
|
16
11
|
padding: 'var(--space-s)',
|
|
@@ -65,13 +60,13 @@ export const DevPagesPanel = () => {
|
|
|
65
60
|
text="design-system.dev.pagesPanel.currentPage"
|
|
66
61
|
style={{ marginBottom: 'var(--space-xs)' }}
|
|
67
62
|
/>
|
|
68
|
-
<Text style={monoStyle}>
|
|
63
|
+
<Text family="mono" font="xs" leading="l" style={monoStyle}>
|
|
69
64
|
<strong><Text as="span" text="design-system.dev.pagesPanel.id" />:</strong> {app?.pageId || '—'}
|
|
70
65
|
</Text>
|
|
71
|
-
<Text style={monoStyle}>
|
|
66
|
+
<Text family="mono" font="xs" leading="l" style={monoStyle}>
|
|
72
67
|
<strong><Text as="span" text="design-system.dev.pagesPanel.path" />:</strong> {currentPathLabel}
|
|
73
68
|
</Text>
|
|
74
|
-
<Text style={monoStyle}>
|
|
69
|
+
<Text family="mono" font="xs" leading="l" style={monoStyle}>
|
|
75
70
|
<strong><Text as="span" text="design-system.dev.pagesPanel.url" />:</strong> {currentUrl}
|
|
76
71
|
</Text>
|
|
77
72
|
{packageDetailHref && currentPage?.package && (
|
|
@@ -94,7 +89,7 @@ export const DevPagesPanel = () => {
|
|
|
94
89
|
|
|
95
90
|
{groups.map(({ key, label, pages: groupPages }) => (
|
|
96
91
|
<View key={key} gap="xs">
|
|
97
|
-
<Text
|
|
92
|
+
<Text weight="bold" font="s">{label}</Text>
|
|
98
93
|
<View gap="xs">
|
|
99
94
|
{groupPages.map((page) => {
|
|
100
95
|
const href = router.getHref(page.id)
|
|
@@ -115,8 +110,8 @@ export const DevPagesPanel = () => {
|
|
|
115
110
|
}}
|
|
116
111
|
>
|
|
117
112
|
<View gap="2px" style={{ alignItems: 'flex-start' }}>
|
|
118
|
-
<Text
|
|
119
|
-
<Text style={{ ...monoStyle, opacity: 0.85 }}>
|
|
113
|
+
<Text family="mono" font="xs" leading="l" weight="bold" style={monoStyle}>{page.id}</Text>
|
|
114
|
+
<Text family="mono" font="xs" leading="l" style={{ ...monoStyle, opacity: 0.85 }}>
|
|
120
115
|
{formatPagePaths(page.path)}
|
|
121
116
|
</Text>
|
|
122
117
|
</View>
|
|
@@ -142,8 +142,8 @@ export function MobileShellNav ({
|
|
|
142
142
|
display: 'flex',
|
|
143
143
|
flexDirection: 'column',
|
|
144
144
|
// Theme primary is glass; over Overlay's dark scrim it reads as a muddy top bar.
|
|
145
|
-
// Use
|
|
146
|
-
background: 'var(--
|
|
145
|
+
// Use the opaque primary so drawer chrome stays readable.
|
|
146
|
+
background: 'var(--surface-primary-solid)',
|
|
147
147
|
backdropFilter: 'none',
|
|
148
148
|
WebkitBackdropFilter: 'none',
|
|
149
149
|
})}
|
|
@@ -68,22 +68,34 @@ export const ThemeEditor = () => {
|
|
|
68
68
|
isEditorOpen && (
|
|
69
69
|
<Overlay isVisible={true} onClose={onToggle}>
|
|
70
70
|
<View layout="off-center" data-component="theme-editor-overlay">
|
|
71
|
-
<View
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
<View
|
|
72
|
+
data-region="content"
|
|
73
|
+
data-component="theme-editor-panel"
|
|
74
|
+
surface="primary"
|
|
75
|
+
roundness="m"
|
|
76
|
+
>
|
|
77
|
+
<View data-component="theme-editor-scroll">
|
|
78
|
+
{/* Column views default to min-height 0, which shrinks this panel instead of scrolling. */}
|
|
79
|
+
<View
|
|
80
|
+
gap="m"
|
|
81
|
+
inset="l"
|
|
82
|
+
style={{ flexShrink: 0, minHeight: 'min-content' }}
|
|
83
|
+
>
|
|
84
|
+
<DevPagesPanel />
|
|
85
|
+
<View as="form" gap="s" onSubmit={onSaveTheme} onChange={onThemeChange}>
|
|
86
|
+
{Object.entries(theme).map(([name, value]) => (
|
|
87
|
+
<div key={name} data-component="theme-editor-field">
|
|
88
|
+
<label>{name}</label>
|
|
89
|
+
<input value={value} data-name={name} />
|
|
90
|
+
</div>
|
|
91
|
+
))}
|
|
92
|
+
<Button type="submit" variant="cta">
|
|
93
|
+
Save
|
|
94
|
+
</Button>
|
|
95
|
+
</View>
|
|
96
|
+
<ThemeSwitcher/>
|
|
97
|
+
<Text>Views: {viewCount}</Text>
|
|
84
98
|
</View>
|
|
85
|
-
<ThemeSwitcher/>
|
|
86
|
-
<Text>Views: {viewCount}</Text>
|
|
87
99
|
</View>
|
|
88
100
|
</View>
|
|
89
101
|
</View>
|
|
@@ -23,7 +23,7 @@ export { resolvePackageHomePageId }
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Build entitlement-filtered sidebar navigation — one link per entitled package
|
|
26
|
-
* that registers a `{slug}/home` page.
|
|
26
|
+
* that registers a `{slug}/home` page, or `{slug}/overview` when home is absent.
|
|
27
27
|
*
|
|
28
28
|
* @param {{
|
|
29
29
|
* manifestSummary?: { packages?: Array<{ slug?: string, package?: string, pages?: Array<{ id: string, title?: string, path?: string | Record<string, string> }> }> }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pick the package
|
|
3
|
-
*
|
|
2
|
+
* Pick the package landing page for sidebar nav.
|
|
3
|
+
* `{slug}/home` wins. `{slug}/overview` is the landing when the package has no home page.
|
|
4
4
|
*
|
|
5
5
|
* @param {Array<{ id?: string }> | undefined} pages
|
|
6
6
|
* @param {string} slug
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export function resolvePackageHomePageId (pages, slug) {
|
|
10
10
|
if (!slug) return null
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const ids = new Set((pages || []).map((page) => page?.id))
|
|
12
|
+
if (ids.has(`${slug}/home`)) return `${slug}/home`
|
|
13
|
+
if (ids.has(`${slug}/overview`)) return `${slug}/overview`
|
|
14
|
+
return null
|
|
14
15
|
}
|
|
@@ -20,12 +20,36 @@ export const themeEditorStyles = `
|
|
|
20
20
|
width: min(720px, 80vw);
|
|
21
21
|
min-width: min(480px, 100%);
|
|
22
22
|
max-height: 85vh;
|
|
23
|
-
overflow
|
|
24
|
-
overflow-x: hidden;
|
|
23
|
+
overflow: hidden;
|
|
25
24
|
margin: 0 auto;
|
|
26
25
|
box-shadow: 2px 2px 5px color-mix(in srgb, var(--foreground) 20%, transparent);
|
|
27
26
|
}
|
|
28
27
|
|
|
28
|
+
[data-component="theme-editor-scroll"] {
|
|
29
|
+
min-height: 0;
|
|
30
|
+
flex: 1 1 auto;
|
|
31
|
+
overflow-x: hidden;
|
|
32
|
+
overflow-y: auto;
|
|
33
|
+
margin: var(--space-s);
|
|
34
|
+
scrollbar-width: thin;
|
|
35
|
+
scrollbar-color: color-mix(in srgb, var(--foreground) 45%, transparent) transparent;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
[data-component="theme-editor-scroll"]::-webkit-scrollbar {
|
|
39
|
+
width: 10px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
[data-component="theme-editor-scroll"]::-webkit-scrollbar-track {
|
|
43
|
+
background: transparent;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
[data-component="theme-editor-scroll"]::-webkit-scrollbar-thumb {
|
|
47
|
+
background: color-mix(in srgb, var(--foreground) 45%, transparent);
|
|
48
|
+
border-radius: 999px;
|
|
49
|
+
border: 3px solid transparent;
|
|
50
|
+
background-clip: padding-box;
|
|
51
|
+
}
|
|
52
|
+
|
|
29
53
|
[data-component="theme-editor-overlay"] {
|
|
30
54
|
height: 100%;
|
|
31
55
|
width: 100%;
|
|
@@ -37,7 +61,7 @@ export const themeEditorStyles = `
|
|
|
37
61
|
|
|
38
62
|
[data-component="theme-editor-field"] label {
|
|
39
63
|
display: block;
|
|
40
|
-
font-family: var(--
|
|
64
|
+
font-family: var(--family-sans, sans-serif);
|
|
41
65
|
margin-bottom: var(--space-xs);
|
|
42
66
|
font-weight: 700;
|
|
43
67
|
}
|