@dxos/plugin-registry 0.7.5-main.9d26e3a → 0.7.5-main.b19bfc8
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/dist/lib/browser/app-graph-builder-Z6FZXJWI.mjs +164 -0
- package/dist/lib/browser/app-graph-builder-Z6FZXJWI.mjs.map +7 -0
- package/dist/lib/browser/chunk-H6GNIIDK.mjs +16 -0
- package/dist/lib/browser/chunk-H6GNIIDK.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +50 -189
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/intent-resolver-QW333HWJ.mjs +23 -0
- package/dist/lib/browser/intent-resolver-QW333HWJ.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/react-surface-6JN3QJEF.mjs +324 -0
- package/dist/lib/browser/react-surface-6JN3QJEF.mjs.map +7 -0
- package/dist/types/src/RegistryPlugin.d.ts +1 -6
- package/dist/types/src/RegistryPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +181 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +180 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts +4 -0
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +4 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/components/PluginDetail.d.ts +8 -0
- package/dist/types/src/components/PluginDetail.d.ts.map +1 -0
- package/dist/types/src/components/PluginDetail.stories.d.ts +8 -0
- package/dist/types/src/components/PluginDetail.stories.d.ts.map +1 -0
- package/dist/types/src/components/PluginItem.d.ts +12 -0
- package/dist/types/src/components/PluginItem.d.ts.map +1 -0
- package/dist/types/src/components/PluginList.d.ts +5 -9
- package/dist/types/src/components/PluginList.d.ts.map +1 -1
- package/dist/types/src/components/PluginList.stories.d.ts +6 -1
- package/dist/types/src/components/PluginList.stories.d.ts.map +1 -1
- package/dist/types/src/components/RegistryContainer.d.ts +6 -0
- package/dist/types/src/components/RegistryContainer.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +2 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +3 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +11 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types.d.ts +6 -0
- package/dist/types/src/types.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +18 -23
- package/src/RegistryPlugin.tsx +26 -41
- package/src/capabilities/app-graph-builder.ts +126 -0
- package/src/capabilities/index.ts +9 -0
- package/src/capabilities/intent-resolver.ts +27 -0
- package/src/capabilities/react-surface.tsx +90 -0
- package/src/components/PluginDetail.stories.tsx +45 -0
- package/src/components/PluginDetail.tsx +63 -0
- package/src/components/PluginItem.tsx +128 -0
- package/src/components/PluginList.stories.tsx +30 -21
- package/src/components/PluginList.tsx +13 -90
- package/src/components/RegistryContainer.tsx +81 -0
- package/src/components/index.ts +2 -1
- package/src/index.ts +1 -4
- package/src/meta.ts +5 -1
- package/src/translations.ts +13 -2
- package/src/types.ts +13 -0
- package/dist/lib/browser/chunk-NEMFDAOB.mjs +0 -12
- package/dist/lib/browser/chunk-NEMFDAOB.mjs.map +0 -7
- package/dist/lib/browser/meta.mjs +0 -9
- package/dist/lib/browser/meta.mjs.map +0 -7
- package/dist/types/src/components/PluginSettings.d.ts +0 -6
- package/dist/types/src/components/PluginSettings.d.ts.map +0 -1
- package/src/components/PluginSettings.tsx +0 -108
|
@@ -2,102 +2,25 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React
|
|
5
|
+
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { type
|
|
8
|
-
import {
|
|
9
|
-
import { descriptionText, fineBlockSize, mx } from '@dxos/react-ui-theme';
|
|
7
|
+
import { type Plugin } from '@dxos/app-framework';
|
|
8
|
+
import { List } from '@dxos/react-ui';
|
|
10
9
|
|
|
11
|
-
import {
|
|
10
|
+
import { PluginItem, type PluginItemProps } from './PluginItem';
|
|
12
11
|
|
|
13
|
-
export type PluginListProps = {
|
|
14
|
-
plugins?:
|
|
15
|
-
loaded?: string[];
|
|
16
|
-
enabled?: string[];
|
|
17
|
-
onChange?: (id: string, enabled: boolean) => void;
|
|
18
|
-
onReload?: () => void;
|
|
12
|
+
export type PluginListProps = Omit<PluginItemProps, 'plugin'> & {
|
|
13
|
+
plugins?: readonly Plugin[];
|
|
19
14
|
};
|
|
20
15
|
|
|
21
|
-
export const PluginList = ({ plugins = [],
|
|
22
|
-
const { t } = useTranslation(REGISTRY_PLUGIN);
|
|
23
|
-
|
|
16
|
+
export const PluginList = ({ plugins = [], ...props }: PluginListProps) => {
|
|
24
17
|
return (
|
|
25
|
-
<List classNames='
|
|
26
|
-
{plugins.map((
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const labelId = `${id}-label`;
|
|
32
|
-
const descriptionId = `${id}-description`;
|
|
33
|
-
const handleChange = useCallback(() => onChange?.(id, !isEnabled), [id, isEnabled, onChange]);
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<Input.Root key={id} id={inputId}>
|
|
37
|
-
<ListItem.Root
|
|
38
|
-
labelId={labelId}
|
|
39
|
-
data-testid={`pluginList.${id}`}
|
|
40
|
-
aria-describedby={descriptionId}
|
|
41
|
-
classNames='flex gap-2 plb-2 pli-2 -mli-2 rounded'
|
|
42
|
-
>
|
|
43
|
-
<Icon icon={icon} size={6} classNames='shrink-0 mbs-1' />
|
|
44
|
-
<div role='none' className={mx(fineBlockSize, 'grow pbs-1 pl-1')}>
|
|
45
|
-
<label htmlFor={inputId} id={labelId} className='truncate'>
|
|
46
|
-
{name ?? id}
|
|
47
|
-
</label>
|
|
48
|
-
{(description || reloadRequired || homePage || source) && (
|
|
49
|
-
<>
|
|
50
|
-
<div id={descriptionId} className='space-b-1 pbs-1 pbe-1'>
|
|
51
|
-
<p className={descriptionText}>{description}</p>
|
|
52
|
-
{homePage && (
|
|
53
|
-
<Link
|
|
54
|
-
href={homePage}
|
|
55
|
-
target='_blank'
|
|
56
|
-
rel='noreferrer'
|
|
57
|
-
aria-describedby={descriptionId}
|
|
58
|
-
classNames='text-xs text-description'
|
|
59
|
-
>
|
|
60
|
-
{t('home page label')}
|
|
61
|
-
<Icon
|
|
62
|
-
icon='ph--arrow-square-out--bold'
|
|
63
|
-
size={3}
|
|
64
|
-
classNames='inline-block leading-none mli-1'
|
|
65
|
-
/>
|
|
66
|
-
</Link>
|
|
67
|
-
)}
|
|
68
|
-
{source && (
|
|
69
|
-
<Link
|
|
70
|
-
href={source}
|
|
71
|
-
target='_blank'
|
|
72
|
-
rel='noreferrer'
|
|
73
|
-
aria-describedby={descriptionId}
|
|
74
|
-
classNames='text-xs text-description'
|
|
75
|
-
>
|
|
76
|
-
{t('source label')}
|
|
77
|
-
<Icon
|
|
78
|
-
icon='ph--arrow-square-out--bold'
|
|
79
|
-
size={3}
|
|
80
|
-
classNames='inline-block leading-none mli-1'
|
|
81
|
-
/>
|
|
82
|
-
</Link>
|
|
83
|
-
)}
|
|
84
|
-
</div>
|
|
85
|
-
{reloadRequired && (
|
|
86
|
-
<Button variant='ghost' classNames='p-0 gap-2' onClick={onReload}>
|
|
87
|
-
<Icon size={4} icon='ph--arrow-clockwise--regular' />
|
|
88
|
-
<p className='text-sm font-medium'>{t('reload required message')}</p>
|
|
89
|
-
</Button>
|
|
90
|
-
)}
|
|
91
|
-
</>
|
|
92
|
-
)}
|
|
93
|
-
</div>
|
|
94
|
-
<div className='pbs-1'>
|
|
95
|
-
<Input.Switch classNames='self-center' checked={isEnabled} onClick={handleChange} />
|
|
96
|
-
</div>
|
|
97
|
-
</ListItem.Root>
|
|
98
|
-
</Input.Root>
|
|
99
|
-
);
|
|
100
|
-
})}
|
|
18
|
+
<List classNames='grid grid-cols-[repeat(auto-fill,minmax(280px,1fr))] auto-rows-[10rem] gap-3 p-3 overflow-y-auto scrollbar-thin'>
|
|
19
|
+
{plugins.map((plugin) => (
|
|
20
|
+
<div key={plugin.meta.id} className='flex'>
|
|
21
|
+
<PluginItem plugin={plugin} {...props} />
|
|
22
|
+
</div>
|
|
23
|
+
))}
|
|
101
24
|
</List>
|
|
102
25
|
);
|
|
103
26
|
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback, useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Capabilities,
|
|
9
|
+
createIntent,
|
|
10
|
+
LayoutAction,
|
|
11
|
+
type Plugin,
|
|
12
|
+
SettingsAction,
|
|
13
|
+
useCapability,
|
|
14
|
+
useIntentDispatcher,
|
|
15
|
+
usePluginManager,
|
|
16
|
+
} from '@dxos/app-framework';
|
|
17
|
+
import { ObservabilityAction } from '@dxos/plugin-observability/types';
|
|
18
|
+
import { StackItem } from '@dxos/react-ui-stack';
|
|
19
|
+
|
|
20
|
+
import { PluginList } from './PluginList';
|
|
21
|
+
|
|
22
|
+
const sortByPluginMeta = ({ meta: { name: a = '' } }: Plugin, { meta: { name: b = '' } }: Plugin) => a.localeCompare(b);
|
|
23
|
+
|
|
24
|
+
export const RegistryContainer = ({ id, plugins: _plugins }: { id: string; plugins: Plugin[] }) => {
|
|
25
|
+
const manager = usePluginManager();
|
|
26
|
+
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
27
|
+
const plugins = useMemo(() => _plugins.sort(sortByPluginMeta), [_plugins]);
|
|
28
|
+
const settingsStore = useCapability(Capabilities.SettingsStore);
|
|
29
|
+
|
|
30
|
+
// TODO(wittjosiah): Factor out to an intent?
|
|
31
|
+
const handleChange = useCallback(
|
|
32
|
+
async (id: string, enabled: boolean) => {
|
|
33
|
+
if (enabled) {
|
|
34
|
+
await manager.enable(id);
|
|
35
|
+
} else {
|
|
36
|
+
await manager.disable(id);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await dispatch(
|
|
40
|
+
createIntent(ObservabilityAction.SendEvent, {
|
|
41
|
+
name: 'plugins.toggle',
|
|
42
|
+
properties: { plugin: id, enabled },
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
[dispatch, manager],
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const handleClick = useCallback(
|
|
50
|
+
(pluginId: string) =>
|
|
51
|
+
dispatch(
|
|
52
|
+
createIntent(LayoutAction.Open, {
|
|
53
|
+
part: 'main',
|
|
54
|
+
// TODO(wittjosiah): `/` currently is not supported in ids.
|
|
55
|
+
subject: [pluginId.replaceAll('/', ':')],
|
|
56
|
+
options: { pivotId: id, positioning: 'end' },
|
|
57
|
+
}),
|
|
58
|
+
),
|
|
59
|
+
[dispatch, id],
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const hasSettings = useCallback((pluginId: string) => !!settingsStore.getStore(pluginId), [settingsStore]);
|
|
63
|
+
|
|
64
|
+
const handleSettings = useCallback(
|
|
65
|
+
(pluginId: string) => dispatch(createIntent(SettingsAction.Open, { plugin: pluginId })),
|
|
66
|
+
[dispatch],
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<StackItem.Content toolbar={false} role='article' classNames='overflow-x-hidden overflow-y-auto'>
|
|
71
|
+
<PluginList
|
|
72
|
+
plugins={plugins}
|
|
73
|
+
enabled={manager.enabled}
|
|
74
|
+
onClick={handleClick}
|
|
75
|
+
onChange={handleChange}
|
|
76
|
+
hasSettings={hasSettings}
|
|
77
|
+
onSettings={handleSettings}
|
|
78
|
+
/>
|
|
79
|
+
</StackItem.Content>
|
|
80
|
+
);
|
|
81
|
+
};
|
package/src/components/index.ts
CHANGED
package/src/index.ts
CHANGED
package/src/meta.ts
CHANGED
|
@@ -6,7 +6,11 @@ import { type PluginMeta } from '@dxos/app-framework';
|
|
|
6
6
|
|
|
7
7
|
export const REGISTRY_PLUGIN = 'dxos.org/plugin/registry';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// TODO(wittjosiah): Deck does not currently support `/` in ids.
|
|
10
|
+
export const REGISTRY_ID = '!dxos:plugin-registry';
|
|
11
|
+
export const REGISTRY_KEY = 'plugin-registry';
|
|
12
|
+
|
|
13
|
+
export const meta = {
|
|
10
14
|
id: REGISTRY_PLUGIN,
|
|
11
15
|
name: 'Plugins',
|
|
12
16
|
} satisfies PluginMeta;
|
package/src/translations.ts
CHANGED
|
@@ -11,11 +11,22 @@ export default [
|
|
|
11
11
|
'plugin name': 'Registry',
|
|
12
12
|
'reload required message': 'Reload required.',
|
|
13
13
|
'settings show experimental label': 'Show experimental plugins',
|
|
14
|
-
'settings section installed label': '
|
|
14
|
+
'settings section installed label': 'Enabled',
|
|
15
15
|
'settings section recommended label': 'Recommended',
|
|
16
16
|
'settings section experimental label': 'Experimental',
|
|
17
|
-
'
|
|
17
|
+
'details label': 'Details',
|
|
18
|
+
'home page label': 'Website',
|
|
18
19
|
'source label': 'Source',
|
|
20
|
+
'plugin registry label': 'Plugin Registry',
|
|
21
|
+
'all plugins label': 'All',
|
|
22
|
+
'installed plugins label': 'Enabled',
|
|
23
|
+
'recommended plugins label': 'Recommended',
|
|
24
|
+
'experimental plugins label': 'Experimental',
|
|
25
|
+
'community plugins label': 'Community',
|
|
26
|
+
'load by url label': 'Load by URL (soon)',
|
|
27
|
+
'coming soon label': 'Coming soon!',
|
|
28
|
+
'open plugin registry label': 'Open plugin registry',
|
|
29
|
+
'settings label': 'Settings',
|
|
19
30
|
},
|
|
20
31
|
},
|
|
21
32
|
},
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { S } from '@dxos/echo-schema';
|
|
6
|
+
|
|
7
|
+
export const RegistrySettingsSchema = S.mutable(
|
|
8
|
+
S.Struct({
|
|
9
|
+
experimental: S.optional(S.Boolean),
|
|
10
|
+
}),
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export type RegistrySettings = S.Schema.Type<typeof RegistrySettingsSchema>;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// packages/plugins/plugin-registry/src/meta.ts
|
|
2
|
-
var REGISTRY_PLUGIN = "dxos.org/plugin/registry";
|
|
3
|
-
var meta_default = {
|
|
4
|
-
id: REGISTRY_PLUGIN,
|
|
5
|
-
name: "Plugins"
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
REGISTRY_PLUGIN,
|
|
10
|
-
meta_default
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=chunk-NEMFDAOB.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/meta.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { type PluginMeta } from '@dxos/app-framework';\n\nexport const REGISTRY_PLUGIN = 'dxos.org/plugin/registry';\n\nexport default {\n id: REGISTRY_PLUGIN,\n name: 'Plugins',\n} satisfies PluginMeta;\n"],
|
|
5
|
-
"mappings": ";AAMO,IAAMA,kBAAkB;AAE/B,IAAA,eAAe;EACbC,IAAID;EACJE,MAAM;AACR;",
|
|
6
|
-
"names": ["REGISTRY_PLUGIN", "id", "name"]
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PluginSettings.d.ts","sourceRoot":"","sources":["../../../../src/components/PluginSettings.tsx"],"names":[],"mappings":"AAIA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAQ/D,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAK/D,eAAO,MAAM,cAAc,iBAAkB;IAAE,QAAQ,EAAE,qBAAqB,CAAA;CAAE,sBAiF/E,CAAC"}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { useMemo, type PropsWithChildren } from 'react';
|
|
6
|
-
|
|
7
|
-
import { createIntent, type PluginMeta, useIntentDispatcher, usePlugins } from '@dxos/app-framework';
|
|
8
|
-
import { ObservabilityAction } from '@dxos/plugin-observability/types';
|
|
9
|
-
import { Input, useTranslation } from '@dxos/react-ui';
|
|
10
|
-
import { DeprecatedFormInput } from '@dxos/react-ui-form';
|
|
11
|
-
|
|
12
|
-
import { PluginList } from './PluginList';
|
|
13
|
-
import { type RegistrySettingsProps } from '../RegistryPlugin';
|
|
14
|
-
import { REGISTRY_PLUGIN } from '../meta';
|
|
15
|
-
|
|
16
|
-
const sortPluginMeta = ({ name: a = '' }: PluginMeta, { name: b = '' }: PluginMeta) => a.localeCompare(b);
|
|
17
|
-
|
|
18
|
-
export const PluginSettings = ({ settings }: { settings: RegistrySettingsProps }) => {
|
|
19
|
-
const { t } = useTranslation(REGISTRY_PLUGIN);
|
|
20
|
-
const { plugins, enabled, core, setPlugin, ...pluginContext } = usePlugins();
|
|
21
|
-
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
22
|
-
|
|
23
|
-
// Memoize to prevent plugins from disappearing when toggling enabled.
|
|
24
|
-
const installed = useMemo(
|
|
25
|
-
() =>
|
|
26
|
-
plugins
|
|
27
|
-
.filter(({ meta }) => !core.includes(meta.id))
|
|
28
|
-
.filter(({ meta }) => enabled.includes(meta.id))
|
|
29
|
-
.map(({ meta }) => meta)
|
|
30
|
-
.sort(sortPluginMeta),
|
|
31
|
-
[],
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const pluginIds = plugins.map(({ meta }) => meta.id);
|
|
35
|
-
const available = useMemo(
|
|
36
|
-
() => pluginContext.available.filter(({ id }) => !enabled.includes(id)).sort(sortPluginMeta),
|
|
37
|
-
[],
|
|
38
|
-
);
|
|
39
|
-
const recommended = available.filter((meta) => !meta.tags?.includes('experimental'));
|
|
40
|
-
const experimental = available.filter((meta) => meta.tags?.includes('experimental'));
|
|
41
|
-
|
|
42
|
-
const handleChange = (id: string, enabled: boolean) => {
|
|
43
|
-
setPlugin(id, enabled);
|
|
44
|
-
void dispatch(
|
|
45
|
-
createIntent(ObservabilityAction.SendEvent, {
|
|
46
|
-
name: 'plugins.toggle',
|
|
47
|
-
properties: { plugin: id, enabled },
|
|
48
|
-
}),
|
|
49
|
-
);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const handleReload = () => {
|
|
53
|
-
window.location.reload();
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<>
|
|
58
|
-
<DeprecatedFormInput label={t('settings show experimental label')}>
|
|
59
|
-
<Input.Switch
|
|
60
|
-
data-testid='pluginSettings.experimental'
|
|
61
|
-
checked={settings.experimental}
|
|
62
|
-
onCheckedChange={(checked) => (settings.experimental = !!checked)}
|
|
63
|
-
/>
|
|
64
|
-
</DeprecatedFormInput>
|
|
65
|
-
|
|
66
|
-
<Section label={t('settings section installed label')}>
|
|
67
|
-
<PluginList
|
|
68
|
-
plugins={installed}
|
|
69
|
-
loaded={pluginIds}
|
|
70
|
-
enabled={enabled}
|
|
71
|
-
onChange={handleChange}
|
|
72
|
-
onReload={handleReload}
|
|
73
|
-
/>
|
|
74
|
-
</Section>
|
|
75
|
-
|
|
76
|
-
<Section label={t('settings section recommended label')}>
|
|
77
|
-
<PluginList
|
|
78
|
-
plugins={recommended}
|
|
79
|
-
loaded={pluginIds}
|
|
80
|
-
enabled={enabled}
|
|
81
|
-
onChange={handleChange}
|
|
82
|
-
onReload={handleReload}
|
|
83
|
-
/>
|
|
84
|
-
</Section>
|
|
85
|
-
|
|
86
|
-
{settings.experimental && (
|
|
87
|
-
<Section label={t('settings section experimental label')}>
|
|
88
|
-
<PluginList
|
|
89
|
-
plugins={experimental}
|
|
90
|
-
loaded={pluginIds}
|
|
91
|
-
enabled={enabled}
|
|
92
|
-
onChange={handleChange}
|
|
93
|
-
onReload={handleReload}
|
|
94
|
-
/>
|
|
95
|
-
</Section>
|
|
96
|
-
)}
|
|
97
|
-
</>
|
|
98
|
-
);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
const Section = ({ label, children }: PropsWithChildren<{ label: string }>) => {
|
|
102
|
-
return (
|
|
103
|
-
<div>
|
|
104
|
-
<h2 className='py-2 text-sm text-subdued'>{label}</h2>
|
|
105
|
-
{children}
|
|
106
|
-
</div>
|
|
107
|
-
);
|
|
108
|
-
};
|