@dxos/plugin-registry 0.13.0 → 0.14.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/dist/lib/chunk-BaseRegistryArticle.mjs +6 -7
- package/dist/lib/chunk-BaseRegistryArticle.mjs.map +1 -1
- package/dist/lib/chunk-PluginArticle.mjs +2 -2
- package/dist/lib/chunk-PluginArticle.mjs.map +1 -1
- package/dist/lib/chunk-PublicRegistryArticle.mjs +2 -2
- package/dist/lib/chunk-PublicRegistryArticle.mjs.map +1 -1
- package/dist/lib/chunk-RegistryArticle.mjs +2 -2
- package/dist/lib/chunk-RegistryArticle.mjs.map +1 -1
- package/dist/lib/chunk-react-surface.mjs +19 -7
- package/dist/lib/chunk-react-surface.mjs.map +1 -1
- package/dist/lib/components.mjs +31 -19
- package/dist/lib/components.mjs.map +1 -1
- package/dist/types/src/capabilities/RegistryCategoryArticle.d.ts +2 -1
- package/dist/types/src/capabilities/RegistryCategoryArticle.d.ts.map +1 -1
- package/dist/types/src/components/PluginFailureBadge/PluginFailureBadge.d.ts.map +1 -1
- package/dist/types/src/components/PluginList/PluginItem.d.ts +2 -1
- package/dist/types/src/components/PluginList/PluginItem.d.ts.map +1 -1
- package/dist/types/src/containers/BaseRegistryArticle/BaseRegistryArticle.d.ts +1 -2
- package/dist/types/src/containers/BaseRegistryArticle/BaseRegistryArticle.d.ts.map +1 -1
- package/dist/types/src/containers/PublicRegistryArticle/PublicRegistryArticle.d.ts +1 -1
- package/dist/types/src/containers/PublicRegistryArticle/PublicRegistryArticle.d.ts.map +1 -1
- package/dist/types/src/containers/RegistryArticle/RegistryArticle.d.ts +1 -1
- package/dist/types/src/containers/RegistryArticle/RegistryArticle.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +30 -30
- package/src/capabilities/RegistryCategoryArticle.tsx +8 -2
- package/src/capabilities/react-surface.ts +5 -5
- package/src/components/PluginDetail/PluginDetail.tsx +17 -15
- package/src/components/PluginFailureBadge/PluginFailureBadge.tsx +3 -2
- package/src/components/PluginList/PluginItem.tsx +7 -3
- package/src/containers/BaseRegistryArticle/BaseRegistryArticle.tsx +4 -13
- package/src/containers/PluginArticle/PluginArticle.tsx +1 -1
- package/src/containers/PublicRegistryArticle/PublicRegistryArticle.tsx +3 -3
- package/src/containers/RegistryArticle/RegistryArticle.tsx +3 -3
- package/src/hooks/usePluginActions.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.mjs","names":[],"sources":["../../src/components/DisableDependentsAlert/DisableDependentsAlert.tsx","../../src/components/PluginFailureBadge/PluginFailureBadge.tsx","../../src/components/PluginDetail/PluginDetail.tsx","../../src/components/PluginList/PluginItem.tsx","../../src/components/PluginList/PluginList.tsx","../../src/components/PluginScope/PluginScope.tsx","../../src/components/RegistrySettings/RegistrySettings.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React from 'react';\n\nimport * as AlertDialog from '@dxos/react-ui/AlertDialog';\nimport * as Hooks from '@dxos/react-ui/Hooks';\n\nimport { meta } from '#meta';\n\nexport type DisableDependentsAlertProps = {\n /** Id of the plugin the user requested to disable. */\n pluginId: string;\n /** Ids of the currently-enabled dependents that would also be disabled. */\n dependents: readonly string[];\n /**\n * Resolves a plugin id to its display name. The component delegates this so\n * the parent can choose how to source names (typically the registered\n * `Plugin.Meta.name`). Falls back to the id when omitted.\n */\n onResolvePluginName?: (pluginId: string) => string;\n onConfirm: () => void;\n};\n\n/**\n * Confirmation prompt shown when a user toggles off a plugin that has\n * currently-enabled dependents. Rendered inside the layout's dialog surface\n * (via `LayoutOperation.UpdateDialog` with `type: 'alert'`), which provides\n * the `AlertDialog.Root` / `Overlay` wrappers — this component renders only\n * the content. `onConfirm` runs the cascade disable and closes the dialog;\n * cancel is handled by the layout's open-change wiring.\n */\nexport const DisableDependentsAlert = ({\n pluginId,\n dependents,\n onResolvePluginName,\n onConfirm,\n}: DisableDependentsAlertProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const resolveName = onResolvePluginName ?? ((id: string) => id);\n return (\n <AlertDialog.Content>\n <AlertDialog.Body>\n <AlertDialog.Title>{t('disable-dependents-dialog.title')}</AlertDialog.Title>\n <AlertDialog.Description>\n {t('disable-dependents-dialog.description', { plugin: resolveName(pluginId) })}\n </AlertDialog.Description>\n <ul className='mt-2 list-disc pl-6 text-sm text-fg-muted'>\n {dependents.map((dependentId) => (\n <li key={dependentId} title={dependentId}>\n {resolveName(dependentId)}\n </li>\n ))}\n </ul>\n </AlertDialog.Body>\n <AlertDialog.Footer>\n <div className='grow' />\n <AlertDialog.Cancel>{t('cancel.label')}</AlertDialog.Cancel>\n <AlertDialog.Action variant='primary' onClick={onConfirm}>\n {t('disable-dependents-dialog.confirm.label')}\n </AlertDialog.Action>\n </AlertDialog.Footer>\n </AlertDialog.Content>\n );\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { type ComponentPropsWithoutRef } from 'react';\n\nimport type * as PluginManager from '@dxos/app-framework/PluginManager';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Popover from '@dxos/react-ui/Popover';\n\nimport { meta } from '#meta';\n\nexport type PluginFailureBadgeProps = {\n failure: PluginManager.PluginFailure;\n /** Size of the warning icon. */\n size?: ComponentPropsWithoutRef<typeof Button.Root>['iconSize'];\n};\n\n/**\n * Compact warning glyph rendered next to a plugin's name when it has failed\n * to load or activate. Clicking the icon opens a popover that names the phase\n * (load / activation), the reason (timeout / error), and the underlying error\n * message — enough for an operator to tell \"remote host is offline\" apart\n * from \"the plugin crashed\".\n */\nexport const PluginFailureBadge = ({ failure, size }: PluginFailureBadgeProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n\n return (\n <Popover.Root>\n <Popover.Trigger asChild>\n <Button.Root\n variant='destructive'\n icon='ph--warning--bold'\n iconOnly\n showTooltip={false}\n iconSize={size}\n label={t('failure-badge.label')}\n data-testid={`pluginFailureBadge.${failure.id}`}\n onClick={(event) => event.stopPropagation()}\n />\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Body>\n <div className='px-3 py-2 min-w-[18rem] max-w-[28rem] flex flex-col gap-1'>\n <p className='font-medium text-sm'>\n {t('failure-title.label', {\n phase: failure.phase === 'load' ? t('failure-phase-load.label') : t('failure-phase-activation.label'),\n reason:\n failure.reason === 'timeout' ? t('failure-reason-timeout.label') : t('failure-reason-error.label'),\n })}\n </p>\n <p className='text-fg-muted text-sm break-words'>{failure.error.message}</p>\n </div>\n </Popover.Body>\n </Popover.Content>\n </Popover.Root>\n );\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type PropsWithChildren, type ReactNode, useMemo } from 'react';\n\nimport type * as Plugin from '@dxos/app-framework/Plugin';\nimport type * as PluginManager from '@dxos/app-framework/PluginManager';\nimport * as ToolkitHooks from '@dxos/app-toolkit/Hooks';\nimport { MarkdownView } from '@dxos/react-ui-markdown';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Carousel from '@dxos/react-ui/Carousel';\nimport * as Field from '@dxos/react-ui/Field';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Icon from '@dxos/react-ui/Icon';\nimport * as Input from '@dxos/react-ui/Input';\nimport * as Layout from '@dxos/react-ui/Layout';\nimport * as ScrollArea from '@dxos/react-ui/ScrollArea';\nimport * as Select from '@dxos/react-ui/Select';\nimport * as Tag from '@dxos/react-ui/Tag';\nimport * as Typography from '@dxos/react-ui/Typography';\nimport * as Util from '@dxos/react-ui/Util';\nimport { getStyles, mx } from '@dxos/ui-theme';\n\nimport { meta } from '#meta';\n\nimport { PluginFailureBadge } from '../PluginFailureBadge/index.ts';\n\nexport type PluginDetailProps = {\n plugin: Plugin.Plugin;\n /** Scope control for this one plugin, rendered under the enable switch. */\n scope?: ReactNode;\n enabled?: boolean;\n /** True while an in-flight install is running. Disables the install button. */\n installing?: boolean;\n /** True while an in-flight update is running. Disables the update button. */\n updating?: boolean;\n /** True when the catalog has a newer version than the one installed. */\n hasUpdate?: boolean;\n /** Currently installed version tag (used to mark the matching select option). */\n installedVersionTag?: string;\n /** Currently selected version tag in the picker. */\n selectedVersionTag?: string;\n /** Available versions of this plugin from the catalog. When non-empty, a version picker is shown. */\n versions?: readonly Plugin.Release[];\n /**\n * Ids of plugins this plugin declares as dependencies (direct only). Rendered\n * under a \"Requires\" heading so the user can see what enabling this plugin\n * will auto-enable.\n */\n dependencies?: readonly string[];\n /**\n * Ids of plugins that declare this plugin as a dependency (direct only).\n * Rendered under a \"Required by\" heading so the user understands the\n * downstream impact of disabling this plugin.\n */\n dependents?: readonly string[];\n /**\n * Failure record for this plugin, if any. When present a warning badge is\n * rendered next to the plugin name in the header.\n */\n failure?: PluginManager.PluginFailure;\n onEnabledChange?: (enabled: boolean) => void;\n /**\n * When provided, the plugin is not installed and an Install button is shown\n * in place of the enable Switch.\n */\n onInstall?: () => void;\n /**\n * Called when the user clicks Install on the version picker.\n */\n onInstallVersion?: () => void;\n /**\n * Called when the user activates a dependency / dependent chip. When\n * provided, chips are rendered as buttons that fire this handler with the\n * target plugin id; when omitted, chips are non-interactive labels.\n */\n onNavigateToPlugin?: (pluginId: string) => void;\n /**\n * Called when the user activates the in-app spec viewer link. When provided\n * (i.e. the plugin bundles its MDL via `Plugin.Meta.specContent`), a second\n * \"View specification\" link is rendered next to the external spec link.\n */\n onOpenSpec?: () => void;\n /**\n * Resolves a plugin id to its display name for dependency / dependent\n * chip labels. The component delegates the lookup to the parent so each\n * surface can decide how to source names (e.g. `Plugin.Meta.name` from the\n * registered plugin set). When omitted, chips render the raw id.\n */\n onResolvePluginName?: (pluginId: string) => string;\n /**\n * When provided, an Uninstall button is rendered. Leave undefined for core\n * or non-removable plugins.\n */\n onUninstall?: () => void;\n /**\n * When provided and the plugin is installed with a newer catalog version available,\n * an Update button is shown in place of the enable Switch.\n */\n onUpdate?: () => void;\n /**\n * Called when the user selects a different version in the picker.\n */\n onVersionChange?: (tag: string) => void;\n};\n\nexport const PluginDetail = Util.composable<HTMLDivElement, PluginDetailProps>(\n (\n {\n plugin,\n scope,\n enabled,\n installing,\n updating,\n hasUpdate,\n installedVersionTag,\n selectedVersionTag,\n versions,\n dependencies,\n dependents,\n failure,\n onEnabledChange,\n onInstall,\n onInstallVersion,\n onNavigateToPlugin,\n onOpenSpec,\n onResolvePluginName,\n onUninstall,\n onUpdate,\n onVersionChange,\n ...props\n },\n forwardedRef,\n ) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const themeMode = Hooks.useThemeMode();\n const layout = ToolkitHooks.useLayout();\n // The gutters exist to hold the icon (col 1) and carousel nav (col 3); on a phone the fixed\n // 4rem floor on both left it with less width for the center content than the gutters themselves.\n const isMobile = layout.mode === 'mobile';\n const { key: slug, name, author, description, homePage, source, screenshots, icon: rawIcon } = plugin.meta.profile;\n const iconKey = rawIcon?.key ?? 'ph--circle--regular';\n const iconHue = rawIcon?.hue ?? 'neutral';\n const styles = getStyles(iconHue);\n\n const versionItems = useMemo(\n () =>\n (versions ?? []).map(({ version }) => ({\n value: version,\n label: installedVersionTag === version ? `${version} (${t('installed.label')})` : version,\n })),\n [versions, installedVersionTag, t],\n );\n\n const resolvedScreenshots = (screenshots ?? [])\n .map((entry) => (themeMode === 'dark' ? (entry.dark ?? entry.light) : (entry.light ?? entry.dark)))\n .filter((url): url is string => typeof url === 'string' && url.length > 0);\n\n return (\n <ScrollArea.Root {...Util.composableProps(props)} orientation='vertical' ref={forwardedRef}>\n <ScrollArea.Viewport>\n {/*\n * 3-column grid: [icon/prev | content/viewport | next].\n * Most sections occupy `col-start-2 col-span-2` so they stretch from\n * the centre column out to the trailing edge. The carousel uses\n * `display: contents` to flatten its children into this grid so\n * `Carousel.Previous` lands in col 1, `Carousel.Viewport` aligns\n * with the rest of the content in col 2, and `Carousel.Next` sits\n * in col 3.\n */}\n <Layout.Grid\n cols={isMobile ? ['2.5rem', 'minmax(0, 1fr)', '2.5rem'] : ['4rem', 'minmax(0, 1fr)', '4rem']}\n align='start'\n classNames='dx-document gap-x-4 p-4'\n >\n <Icon.Icon\n classNames={mx('row-start-1 p-1 rounded-md', isMobile ? 'size-8' : 'size-14', styles.bg, styles.fg)}\n icon={iconKey}\n />\n\n <Layout.Grid cols={['fill', 'min']} classNames='row-start-1 col-start-2 col-span-2 gap-x-3 w-full pt-1'>\n <div className='flex items-center gap-2'>\n <h2 className='text-xl'>{name}</h2>\n {failure && <PluginFailureBadge failure={failure} size='lg' />}\n </div>\n {onInstall ? (\n <Button.Root size='md' variant='primary' disabled={installing} onClick={onInstall}>\n {installing ? t('installing.label') : t('install.label')}\n </Button.Root>\n ) : (\n <Field.Root>\n <Input.Switch\n classNames='self-center'\n checked={enabled}\n onCheckedChange={({ checked }) => onEnabledChange?.(checked)}\n />\n </Field.Root>\n )}\n <div className='flex items-center gap-1 pt-0.5 text-sm text-fg-muted'>\n {slug}\n {author && (\n <span className='dx-tag dx-tag-inline' data-hue='info'>\n {author}\n </span>\n )}\n </div>\n </Layout.Grid>\n\n {scope && (\n <Section.Root>\n <Section.Heading title={t('plugin-scope.section.title')} />\n <Section.Body>{scope}</Section.Body>\n </Section.Root>\n )}\n\n {description && (\n <Section.Root>\n <Section.Heading title={t('description.label')} />\n <Section.Body>\n <MarkdownView classNames='text-fg-muted' content={description} />\n </Section.Body>\n </Section.Root>\n )}\n\n {resolvedScreenshots.length > 0 && (\n <Section.Root>\n <Section.Heading title={t('preview.label')} />\n <Section.Body>\n <Carousel.Root count={resolvedScreenshots.length}>\n <Carousel.ItemGroup>\n {resolvedScreenshots.map((src, index) => (\n <Carousel.Item key={src} index={index} src={src} alt={name} />\n ))}\n </Carousel.ItemGroup>\n <Carousel.IndicatorGroup />\n </Carousel.Root>\n </Section.Body>\n </Section.Root>\n )}\n\n <Section.Root>\n <Section.Heading title={t('resources.label')} />\n <Section.Body>\n <div className='flex gap-3 items-center'>\n {homePage && (\n <Typography.Link href={homePage} classNames='text-sm text-fg-muted'>\n {t('home-page.label')}\n <Icon.Icon\n icon='ph--arrow-square-out--regular'\n size='xs'\n classNames='ml-1 inline-block align-[-0.125em]'\n />\n </Typography.Link>\n )}\n\n {source && (\n <Typography.Link href={source} classNames='text-sm text-fg-muted'>\n {t('source.label')}\n <Icon.Icon\n icon='ph--arrow-square-out--regular'\n size='xs'\n classNames='ml-1 inline-block align-[-0.125em]'\n />\n </Typography.Link>\n )}\n\n {onOpenSpec && <Chip id={slug} name={t('open-spec.label')} onClick={onOpenSpec} />}\n </div>\n </Section.Body>\n </Section.Root>\n\n {dependencies && dependencies.length > 0 && (\n <Section.Root>\n <Section.Heading title={t('dependencies.label')} />\n <Section.Body>\n <div className='flex flex-wrap gap-1'>\n {dependencies.map((depId) => (\n <Chip\n key={depId}\n id={depId}\n name={onResolvePluginName?.(depId) ?? depId}\n onClick={onNavigateToPlugin}\n />\n ))}\n </div>\n </Section.Body>\n </Section.Root>\n )}\n\n {dependents && dependents.length > 0 && (\n <Section.Root>\n <Section.Heading title={t('dependents.label')} />\n <Section.Body>\n <div className='flex flex-wrap gap-1'>\n {dependents.map((dependentId) => (\n <Chip\n key={dependentId}\n id={dependentId}\n name={onResolvePluginName?.(dependentId) ?? dependentId}\n onClick={onNavigateToPlugin}\n />\n ))}\n </div>\n </Section.Body>\n </Section.Root>\n )}\n\n {versions && versions.length > 0 && (\n <Section.Root>\n <Section.Heading title={t('versions.label')} />\n <Section.Body>\n <div className='flex gap-2 items-center'>\n <Select.Root\n items={versionItems}\n value={selectedVersionTag ? [selectedVersionTag] : []}\n onValueChange={({ value: [value] }) => value && onVersionChange?.(value)}\n >\n <Select.Trigger classNames='min-w-32' />\n <Select.Content>\n {versionItems.map((item) => (\n <Select.Item key={item.value} item={item} />\n ))}\n </Select.Content>\n </Select.Root>\n {onInstallVersion && (\n <Button.Root\n size='md'\n variant='primary'\n disabled={installing || selectedVersionTag === installedVersionTag}\n onClick={onInstallVersion}\n >\n {installing ? t('installing.label') : t('install-version.label')}\n </Button.Root>\n )}\n </div>\n </Section.Body>\n </Section.Root>\n )}\n\n {(onUninstall || (hasUpdate && onUpdate) || updating) && (\n <div className='col-start-2 col-span-2 flex gap-2'>\n {updating ? (\n <Button.Root variant='primary' disabled>\n {t('updating.label')}\n </Button.Root>\n ) : hasUpdate && onUpdate ? (\n <Button.Root variant='primary' onClick={onUpdate}>\n {t('update.label')}\n </Button.Root>\n ) : null}\n {onUninstall && <Button.Root onClick={onUninstall}>{t('uninstall.label')}</Button.Root>}\n </div>\n )}\n </Layout.Grid>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n );\n },\n);\n\nPluginDetail.displayName = 'PluginDetail';\n\nconst SectionRoot = ({ children }: PropsWithChildren<{}>) => <>{children}</>;\n\nconst SectionHeading = ({ title }: { title: string }) => (\n <h2 className='col-start-2 col-span-2 pt-6 pb-2 uppercase text-sm font-medium text-fg-subtle'>{title}</h2>\n);\n\nconst SectionBody = ({ classNames, children }: Util.ThemedClassName<PropsWithChildren>) => (\n <div className={mx('col-start-2 flex flex-col gap-2', classNames)}>{children}</div>\n);\n\nconst Section = {\n Root: SectionRoot,\n Heading: SectionHeading,\n Body: SectionBody,\n};\n\nconst Chip = ({ id, name, onClick }: { id: string; name: string; onClick?: (pluginId: string) => void }) => (\n <Tag.Tag title={id} onClick={onClick ? () => onClick(id) : undefined} classNames='dx-hover'>\n {name}\n </Tag.Tag>\n);\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { useCallback, useMemo } from 'react';\n\nimport type * as Plugin from '@dxos/app-framework/Plugin';\nimport type * as PluginManager from '@dxos/app-framework/PluginManager';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Card from '@dxos/react-ui/Card';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Icon from '@dxos/react-ui/Icon';\nimport * as Input from '@dxos/react-ui/Input';\nimport * as Tag from '@dxos/react-ui/Tag';\nimport * as Typography from '@dxos/react-ui/Typography';\nimport { ACCENT_HUES } from '@dxos/ui-theme';\n\nimport { meta } from '#meta';\nimport { type RegistryTagType } from '#types';\n\nimport { PluginFailureBadge } from '../PluginFailureBadge/index.ts';\n\nexport type PluginItemProps = {\n plugin: Plugin.Plugin;\n /** Ids of plugins currently installed (loaded into the manager). */\n installed?: readonly string[];\n /** Ids of plugins whose install is in flight. */\n installing?: readonly string[];\n enabled?: readonly string[];\n /**\n * Derived tags (e.g. `registry`, `local`) to display alongside the plugin's own meta.tags.\n * Not persisted to plugin meta; computed per-render by the container.\n */\n extraTags?: readonly string[];\n /** Whether this device's answer for this plugin differs from the account's. */\n deviceOnly?: boolean;\n onClick?: (id: string) => void;\n onChange?: (id: string, enabled: boolean) => void;\n /**\n * Install handler. When provided and the plugin is not installed, an Install button\n * is rendered in place of the enable switch.\n */\n onInstall?: (id: string) => void;\n /**\n * When true and plugin is installed, shows an Update button instead of the enable switch.\n */\n hasUpdate?: boolean;\n /** Called when the user clicks the Update button. */\n onUpdate?: (id: string) => void;\n /** Ids of plugins whose update is currently in flight. */\n updating?: readonly string[];\n hasSettings?: (id: string) => boolean;\n onSettings?: (id: string) => void;\n /**\n * Failure record for this plugin, if any. When present a warning badge is\n * rendered next to the plugin name; clicking it opens a popover with the\n * phase, reason, and error message.\n */\n failure?: PluginManager.PluginFailure;\n readOnly?: boolean;\n};\n\nexport const PluginItem = ({\n plugin,\n installed,\n installing,\n enabled = [],\n extraTags,\n deviceOnly,\n onClick,\n onChange,\n onInstall,\n hasUpdate,\n onUpdate,\n updating,\n hasSettings: hasSettingsProp,\n onSettings,\n failure,\n readOnly,\n}: PluginItemProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const { key: id, name, description, tags, icon: rawIcon } = plugin.meta.profile;\n const icon = rawIcon?.key ?? 'ph--circle--regular';\n // The manifest's hue is a free string; only a palette hue reaches the icon.\n const hue = ACCENT_HUES.find((candidate) => candidate === rawIcon?.hue);\n const displayTags = useMemo(() => {\n if (!extraTags || extraTags.length === 0) {\n return tags ?? [];\n }\n const set = new Set<string>(tags ?? []);\n for (const tag of extraTags) {\n set.add(tag);\n }\n return Array.from(set);\n }, [tags, extraTags]);\n const isEnabled = enabled.includes(id);\n const isInstalled = installed ? installed.includes(id) : true;\n const isInstalling = installing?.includes(id) ?? false;\n const isUpdating = updating?.includes(id) ?? false;\n const showInstallButton = !!onInstall && !isInstalled;\n const showUpdateButton = !!onUpdate && isInstalled && !!hasUpdate;\n const hasSettings = hasSettingsProp?.(id) ?? false;\n const titleId = `${id}-title`;\n const handleClick = useCallback(() => onClick?.(id), [id, onClick]);\n const handleSettings = useCallback(() => onSettings?.(id), [id, onSettings]);\n const handleInstall = useCallback(() => onInstall?.(id), [id, onInstall]);\n const handleUpdate = useCallback(() => onUpdate?.(id), [id, onUpdate]);\n\n return (\n <Card.Root role='listitem' aria-labelledby={titleId} data-testid={`pluginList.${id}`}>\n <Card.Tile icon={icon} hue={hue} aria-label={t('details.label')} onClick={handleClick} />\n <Card.Body>\n <Card.Header>\n <Card.Title id={titleId} truncate>\n {name ?? id}\n </Card.Title>\n {failure && <PluginFailureBadge failure={failure} />}\n {deviceOnly && (\n <Icon.Icon data-testid={`pluginList.${id}.deviceOnly`} icon='ph--monitor--regular' tone='muted' />\n )}\n </Card.Header>\n {description && (\n <Typography.Text tone='muted' lines={4}>\n {description}\n </Typography.Text>\n )}\n {displayTags.length > 0 && (\n <Button.Group>\n {displayTags.map((tag) => (\n <Tag.Tag key={tag} hue={tagColors[tag as RegistryTagType]}>\n {tag.toUpperCase()}\n </Tag.Tag>\n ))}\n </Button.Group>\n )}\n <Card.Footer justify='between'>\n <Button.Group>\n <Button.Root\n variant='ghost'\n iconOnly\n icon='ph--gear--regular'\n label={t('plugin-settings.label')}\n disabled={!hasSettings}\n onClick={handleSettings}\n />\n <Typography.Link asChild variant='neutral'>\n <button type='button' onClick={handleClick}>\n {t('details.label')}\n </button>\n </Typography.Link>\n </Button.Group>\n {isUpdating ? (\n <Button.Root variant='primary' disabled label={t('updating.label')} />\n ) : showUpdateButton ? (\n <Button.Root variant='primary' label={t('update.label')} onClick={handleUpdate} />\n ) : showInstallButton ? (\n <Button.Root\n variant='primary'\n disabled={isInstalling}\n label={isInstalling ? t('installing.label') : t('install.label')}\n onClick={handleInstall}\n />\n ) : (\n <Input.Switch\n aria-label={name ?? id}\n checked={isEnabled}\n disabled={readOnly}\n onCheckedChange={({ checked }) => onChange?.(id, checked)}\n />\n )}\n </Card.Footer>\n </Card.Body>\n </Card.Root>\n );\n};\n\nconst tagColors: Record<RegistryTagType, Tag.TagHue> = {\n new: 'rose',\n // Tier hues ramp green -> blue -> purple so the ordering reads without knowing the labels.\n beta: 'green',\n alpha: 'blue',\n labs: 'purple',\n popular: 'green',\n featured: 'pink',\n experimental: 'amber',\n registry: 'indigo',\n local: 'neutral',\n};\n","//\n// Copyright 2023 DXOS.org\n//\n\nimport React from 'react';\n\nimport type * as Plugin from '@dxos/app-framework/Plugin';\nimport type * as PluginManager from '@dxos/app-framework/PluginManager';\nimport * as Layout from '@dxos/react-ui/Layout';\n\nimport { PluginItem, type PluginItemProps } from './PluginItem.tsx';\n\nexport type PluginListProps = Omit<PluginItemProps, 'plugin' | 'extraTags' | 'hasUpdate' | 'failure'> & {\n plugins?: readonly Plugin.Plugin[];\n /**\n * Map from plugin id → extra tags to display (e.g. `registry`, `local`).\n * Computed by the container; not persisted to plugin meta.\n */\n extraTagsById?: Record<string, readonly string[]>;\n /**\n * Set of plugin ids for which a newer version is available in the catalog.\n * Causes each matching item to render an Update button instead of the enable switch.\n */\n updateAvailableIds?: ReadonlySet<string>;\n /**\n * Map from plugin id → most recent failure record. Used to render a warning\n * badge next to the plugin name. Sourced from `PluginManager.failed`.\n */\n failuresById?: Record<string, PluginManager.PluginFailure>;\n /** Ids whose value on this device differs from the account's. */\n deviceOnlyIds?: ReadonlySet<string>;\n};\n\nexport const PluginList = ({\n plugins = [],\n extraTagsById,\n updateAvailableIds,\n failuresById,\n deviceOnlyIds,\n ...props\n}: PluginListProps) => {\n return (\n <Layout.Container\n layout='row'\n columns='repeat(auto-fill, minmax(18rem, 1fr))'\n gap='lg'\n align='stretch'\n role='list'\n aria-label='plugins'\n >\n {plugins.map((plugin) => (\n <PluginItem\n key={plugin.meta.profile.key}\n plugin={plugin}\n extraTags={extraTagsById?.[plugin.meta.profile.key]}\n hasUpdate={updateAvailableIds?.has(plugin.meta.profile.key)}\n failure={failuresById?.[plugin.meta.profile.key]}\n deviceOnly={deviceOnlyIds?.has(plugin.meta.profile.key)}\n {...props}\n />\n ))}\n </Layout.Container>\n );\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback } from 'react';\n\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as ToggleGroup from '@dxos/react-ui/ToggleGroup';\n\nimport { meta } from '#meta';\n\nexport type PluginScopeProps = {\n /** Whether this plugin's enabled state follows the account rather than being pinned here. */\n synced: boolean;\n /** Keep this plugin's state on this device. */\n onPin: () => void;\n /** Hand this plugin's state back to the account. */\n onUnpin: () => void;\n};\n\n/** Whether one plugin's enabled state follows the account or is pinned to this device. */\nexport const PluginScope = ({ synced, onPin, onUnpin }: PluginScopeProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const handleValueChange = useCallback(\n (value: string) => {\n if (value === 'shared' && !synced) {\n onUnpin();\n } else if (value === 'local' && synced) {\n onPin();\n }\n },\n [onPin, onUnpin, synced],\n );\n\n return (\n <ToggleGroup.Root type='single' value={synced ? 'shared' : 'local'} onValueChange={handleValueChange}>\n <ToggleGroup.Item\n value='shared'\n data-testid='pluginDetail.scope.shared'\n icon='ph--cloud-check--regular'\n label={t('plugin-scope.shared.label')}\n iconOnly\n />\n <ToggleGroup.Item\n value='local'\n data-testid='pluginDetail.scope.local'\n icon='ph--monitor--regular'\n label={t('plugin-scope.device-only.label')}\n iconOnly\n />\n </ToggleGroup.Root>\n );\n};\n\nPluginScope.displayName = 'PluginScope';\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport type * as AppSurface from '@dxos/app-toolkit/AppSurface';\nimport { log } from '@dxos/log';\nimport { Form } from '@dxos/react-ui-form';\nimport * as AlertDialog from '@dxos/react-ui/AlertDialog';\nimport * as Banner from '@dxos/react-ui/Banner';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Field from '@dxos/react-ui/Field';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Input from '@dxos/react-ui/Input';\n\nimport { meta } from '#meta';\nimport { RegistrySettingsSchema, type RegistrySettings as RegistrySettingsType } from '#types';\n\nexport type RegistrySettingsProps = AppSurface.SettingsProps<\n RegistrySettingsType,\n {\n activeDevPluginIds: readonly string[];\n onEnableDev: (url: string) => Promise<void>;\n onDisableDev: (id: string) => Promise<void>;\n /** Whether this device uses its own plugin set rather than the account's; `undefined` hides the section. */\n pluginScopeLocal?: boolean;\n onPluginScopeLocalChange?: (local: boolean) => void;\n }\n>;\n\n/**\n * Settings panel for `@dxos/plugin-registry`. The dev-plugin section lets a\n * plugin author point Composer at a local Vite dev server (defaults to\n * `localhost:3967`) and toggle the dev plugin on/off persistently — boot will\n * re-attach it on the next reload, surviving HMR-triggered reloads. If the\n * dev server is offline at boot, the toggle stays on and a warning is logged\n * (the manager's `failed` atom also surfaces a badge on the plugin list).\n *\n * The URL input and toggle are rendered as `Form.Field` action rows (not schema\n * fields): the input needs a dynamic disabled state and the toggle runs async\n * enable/disable side effects, neither of which a plain schema field expresses.\n */\nexport const RegistrySettings = ({\n settings,\n onSettingsChange,\n activeDevPluginIds,\n onEnableDev,\n onDisableDev,\n pluginScopeLocal,\n onPluginScopeLocalChange,\n scope,\n}: RegistrySettingsProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const [rejoining, setRejoining] = useState(false);\n const [busy, setBusy] = useState(false);\n const enabled = !!settings.devPluginEnabled;\n const url = settings.devPluginUrl ?? '';\n const trimmedUrl = url.trim();\n const loadedDevId = activeDevPluginIds[0];\n\n const handleToggle = useCallback(async () => {\n if (busy || !onSettingsChange) {\n return;\n }\n setBusy(true);\n try {\n if (enabled && loadedDevId) {\n await onDisableDev(loadedDevId);\n onSettingsChange((current) => ({ ...current, devPluginEnabled: false }));\n } else if (enabled) {\n // Toggle is on but no dev plugin is currently loaded (boot-time load\n // failed or hasn't finished). Treat the click as \"turn it off.\"\n onSettingsChange((current) => ({ ...current, devPluginEnabled: false }));\n } else {\n if (!trimmedUrl) {\n return;\n }\n // Optimistically persist intent so the next reload retries even if\n // the page closes mid-load.\n onSettingsChange((current) => ({ ...current, devPluginEnabled: true }));\n try {\n await onEnableDev(trimmedUrl);\n } catch (error) {\n // Per product direction: leave the intent on, log the failure. The\n // user explicitly turns it off if they're done iterating.\n log.warn('dev plugin enable failed', { url: trimmedUrl, error });\n }\n }\n } finally {\n setBusy(false);\n }\n }, [busy, enabled, loadedDevId, onSettingsChange, onDisableDev, onEnableDev, trimmedUrl]);\n\n // Button label tracks the persisted intent, not the current load state, so\n // a transient \"intent on but not loaded\" combination still reads as\n // \"Disable Dev Plugin\" — clicking it turns the intent off cleanly.\n const buttonLabel = busy\n ? t('dev-plugin.busy.label')\n : enabled\n ? t('dev-plugin.disable.label')\n : t('dev-plugin.enable.label');\n\n return (\n <Form.Root variant='settings' readonly={!onSettingsChange} schema={RegistrySettingsSchema} values={settings}>\n <Form.Viewport scroll>\n <Form.Content>\n {pluginScopeLocal !== undefined && (\n <Form.FieldSet label={t('plugin-registry.label')} actions={scope}>\n <Form.Field label={t('plugin-scope.label')} description={t('plugin-scope.description')}>\n <Field.Root>\n <Input.Switch\n data-testid='registrySettings.pluginScope'\n // The scope is still worth showing without a handler; flipping it is not.\n disabled={!onPluginScopeLocalChange}\n checked={pluginScopeLocal}\n // Only rejoining asks: it replaces this device's choices with the account's.\n onCheckedChange={({ checked: local }) =>\n local ? onPluginScopeLocalChange?.(true) : setRejoining(true)\n }\n />\n </Field.Root>\n </Form.Field>\n </Form.FieldSet>\n )}\n <Form.FieldSet label={t('dev-plugin.section.title')}>\n <Banner.Root valence='neutral'>\n <Banner.Body>{t('dev-plugin.description')}</Banner.Body>\n </Banner.Root>\n <Form.Field label={t('dev-plugin.url.label')} description={t('dev-plugin.url.description')}>\n <Input.Root\n data-testid='registrySettings.devPluginUrl'\n disabled={!onSettingsChange || enabled || busy}\n value={url}\n onChange={(event) =>\n onSettingsChange?.((current) => ({ ...current, devPluginUrl: event.target.value }))\n }\n />\n </Form.Field>\n <Form.Field\n standalone\n label={t('dev-plugin.toggle.label')}\n description={t('dev-plugin.toggle.description')}\n >\n <Button.Root\n data-testid='registrySettings.devPluginToggle'\n variant={enabled ? undefined : 'primary'}\n disabled={!onSettingsChange || busy || (!enabled && !trimmedUrl)}\n onClick={() => void handleToggle()}\n >\n {buttonLabel}\n </Button.Root>\n </Form.Field>\n {enabled && !loadedDevId && !busy && (\n <Banner.Root valence='warning'>\n <Banner.Body>{t('dev-plugin.not-loaded.message')}</Banner.Body>\n </Banner.Root>\n )}\n </Form.FieldSet>\n </Form.Content>\n </Form.Viewport>\n <AlertDialog.Root open={rejoining} onOpenChange={({ open }) => setRejoining(open)}>\n <AlertDialog.Content>\n <AlertDialog.Body>\n <AlertDialog.Title>{t('plugin-scope.rejoin-dialog.title')}</AlertDialog.Title>\n <AlertDialog.Description>{t('plugin-scope.rejoin-dialog.description')}</AlertDialog.Description>\n </AlertDialog.Body>\n <AlertDialog.Footer>\n <div className='grow' />\n <AlertDialog.Cancel>{t('plugin-scope.rejoin-dialog.cancel.label')}</AlertDialog.Cancel>\n <AlertDialog.Action\n data-testid='registrySettings.pluginScope.confirm'\n variant='primary'\n onClick={() => {\n onPluginScopeLocalChange?.(false);\n setRejoining(false);\n }}\n >\n {t('plugin-scope.rejoin-dialog.confirm.label')}\n </AlertDialog.Action>\n </AlertDialog.Footer>\n </AlertDialog.Content>\n </AlertDialog.Root>\n </Form.Root>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"components.mjs","names":[],"sources":["../../src/components/DisableDependentsAlert/DisableDependentsAlert.tsx","../../src/components/PluginFailureBadge/PluginFailureBadge.tsx","../../src/components/PluginDetail/PluginDetail.tsx","../../src/components/PluginList/PluginItem.tsx","../../src/components/PluginList/PluginList.tsx","../../src/components/PluginScope/PluginScope.tsx","../../src/components/RegistrySettings/RegistrySettings.tsx"],"sourcesContent":["//\n// Copyright 2026 DXOS.org\n//\n\nimport React from 'react';\n\nimport * as AlertDialog from '@dxos/react-ui/AlertDialog';\nimport * as Hooks from '@dxos/react-ui/Hooks';\n\nimport { meta } from '#meta';\n\nexport type DisableDependentsAlertProps = {\n /** Id of the plugin the user requested to disable. */\n pluginId: string;\n /** Ids of the currently-enabled dependents that would also be disabled. */\n dependents: readonly string[];\n /**\n * Resolves a plugin id to its display name. The component delegates this so\n * the parent can choose how to source names (typically the registered\n * `Plugin.Meta.name`). Falls back to the id when omitted.\n */\n onResolvePluginName?: (pluginId: string) => string;\n onConfirm: () => void;\n};\n\n/**\n * Confirmation prompt shown when a user toggles off a plugin that has\n * currently-enabled dependents. Rendered inside the layout's dialog surface\n * (via `LayoutOperation.UpdateDialog` with `type: 'alert'`), which provides\n * the `AlertDialog.Root` / `Overlay` wrappers — this component renders only\n * the content. `onConfirm` runs the cascade disable and closes the dialog;\n * cancel is handled by the layout's open-change wiring.\n */\nexport const DisableDependentsAlert = ({\n pluginId,\n dependents,\n onResolvePluginName,\n onConfirm,\n}: DisableDependentsAlertProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const resolveName = onResolvePluginName ?? ((id: string) => id);\n return (\n <AlertDialog.Content>\n <AlertDialog.Body>\n <AlertDialog.Title>{t('disable-dependents-dialog.title')}</AlertDialog.Title>\n <AlertDialog.Description>\n {t('disable-dependents-dialog.description', { plugin: resolveName(pluginId) })}\n </AlertDialog.Description>\n <ul className='mt-2 list-disc pl-6 text-sm text-fg-muted'>\n {dependents.map((dependentId) => (\n <li key={dependentId} title={dependentId}>\n {resolveName(dependentId)}\n </li>\n ))}\n </ul>\n </AlertDialog.Body>\n <AlertDialog.Footer>\n <div className='grow' />\n <AlertDialog.Cancel>{t('cancel.label')}</AlertDialog.Cancel>\n <AlertDialog.Action variant='primary' onClick={onConfirm}>\n {t('disable-dependents-dialog.confirm.label')}\n </AlertDialog.Action>\n </AlertDialog.Footer>\n </AlertDialog.Content>\n );\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { type ComponentPropsWithoutRef } from 'react';\n\nimport type * as PluginManager from '@dxos/app-framework/PluginManager';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Layout from '@dxos/react-ui/Layout';\nimport * as Popover from '@dxos/react-ui/Popover';\n\nimport { meta } from '#meta';\n\nexport type PluginFailureBadgeProps = {\n failure: PluginManager.PluginFailure;\n /** Size of the warning icon. */\n size?: ComponentPropsWithoutRef<typeof Button.Root>['iconSize'];\n};\n\n/**\n * Compact warning glyph rendered next to a plugin's name when it has failed\n * to load or activate. Clicking the icon opens a popover that names the phase\n * (load / activation), the reason (timeout / error), and the underlying error\n * message — enough for an operator to tell \"remote host is offline\" apart\n * from \"the plugin crashed\".\n */\nexport const PluginFailureBadge = ({ failure, size }: PluginFailureBadgeProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n\n return (\n <Popover.Root>\n <Popover.Trigger asChild>\n <Button.Root\n variant='destructive'\n icon='ph--warning--bold'\n iconOnly\n showTooltip={false}\n iconSize={size}\n label={t('failure-badge.label')}\n data-testid={`pluginFailureBadge.${failure.id}`}\n onClick={(event) => event.stopPropagation()}\n />\n </Popover.Trigger>\n <Popover.Content>\n <Popover.Body>\n <Layout.Flex column gap='xs' classNames='px-3 py-2 min-w-[18rem] max-w-[28rem]'>\n <p className='font-medium text-sm'>\n {t('failure-title.label', {\n phase: failure.phase === 'load' ? t('failure-phase-load.label') : t('failure-phase-activation.label'),\n reason:\n failure.reason === 'timeout' ? t('failure-reason-timeout.label') : t('failure-reason-error.label'),\n })}\n </p>\n <p className='text-fg-muted text-sm break-words'>{failure.error.message}</p>\n </Layout.Flex>\n </Popover.Body>\n </Popover.Content>\n </Popover.Root>\n );\n};\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type PropsWithChildren, type ReactNode, useMemo } from 'react';\n\nimport type * as Plugin from '@dxos/app-framework/Plugin';\nimport type * as PluginManager from '@dxos/app-framework/PluginManager';\nimport * as ToolkitHooks from '@dxos/app-toolkit/Hooks';\nimport { MarkdownView } from '@dxos/react-ui-markdown';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Carousel from '@dxos/react-ui/Carousel';\nimport * as Field from '@dxos/react-ui/Field';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Icon from '@dxos/react-ui/Icon';\nimport * as Input from '@dxos/react-ui/Input';\nimport * as Layout from '@dxos/react-ui/Layout';\nimport * as ScrollArea from '@dxos/react-ui/ScrollArea';\nimport * as Select from '@dxos/react-ui/Select';\nimport * as Tag from '@dxos/react-ui/Tag';\nimport * as Typography from '@dxos/react-ui/Typography';\nimport * as Util from '@dxos/react-ui/Util';\nimport { getStyles, mx } from '@dxos/ui-theme';\n\nimport { meta } from '#meta';\n\nimport { PluginFailureBadge } from '../PluginFailureBadge/index.ts';\n\nexport type PluginDetailProps = {\n plugin: Plugin.Plugin;\n /** Scope control for this one plugin, rendered under the enable switch. */\n scope?: ReactNode;\n enabled?: boolean;\n /** True while an in-flight install is running. Disables the install button. */\n installing?: boolean;\n /** True while an in-flight update is running. Disables the update button. */\n updating?: boolean;\n /** True when the catalog has a newer version than the one installed. */\n hasUpdate?: boolean;\n /** Currently installed version tag (used to mark the matching select option). */\n installedVersionTag?: string;\n /** Currently selected version tag in the picker. */\n selectedVersionTag?: string;\n /** Available versions of this plugin from the catalog. When non-empty, a version picker is shown. */\n versions?: readonly Plugin.Release[];\n /**\n * Ids of plugins this plugin declares as dependencies (direct only). Rendered\n * under a \"Requires\" heading so the user can see what enabling this plugin\n * will auto-enable.\n */\n dependencies?: readonly string[];\n /**\n * Ids of plugins that declare this plugin as a dependency (direct only).\n * Rendered under a \"Required by\" heading so the user understands the\n * downstream impact of disabling this plugin.\n */\n dependents?: readonly string[];\n /**\n * Failure record for this plugin, if any. When present a warning badge is\n * rendered next to the plugin name in the header.\n */\n failure?: PluginManager.PluginFailure;\n onEnabledChange?: (enabled: boolean) => void;\n /**\n * When provided, the plugin is not installed and an Install button is shown\n * in place of the enable Switch.\n */\n onInstall?: () => void;\n /**\n * Called when the user clicks Install on the version picker.\n */\n onInstallVersion?: () => void;\n /**\n * Called when the user activates a dependency / dependent chip. When\n * provided, chips are rendered as buttons that fire this handler with the\n * target plugin id; when omitted, chips are non-interactive labels.\n */\n onNavigateToPlugin?: (pluginId: string) => void;\n /**\n * Called when the user activates the in-app spec viewer link. When provided\n * (i.e. the plugin bundles its MDL via `Plugin.Meta.specContent`), a second\n * \"View specification\" link is rendered next to the external spec link.\n */\n onOpenSpec?: () => void;\n /**\n * Resolves a plugin id to its display name for dependency / dependent\n * chip labels. The component delegates the lookup to the parent so each\n * surface can decide how to source names (e.g. `Plugin.Meta.name` from the\n * registered plugin set). When omitted, chips render the raw id.\n */\n onResolvePluginName?: (pluginId: string) => string;\n /**\n * When provided, an Uninstall button is rendered. Leave undefined for core\n * or non-removable plugins.\n */\n onUninstall?: () => void;\n /**\n * When provided and the plugin is installed with a newer catalog version available,\n * an Update button is shown in place of the enable Switch.\n */\n onUpdate?: () => void;\n /**\n * Called when the user selects a different version in the picker.\n */\n onVersionChange?: (tag: string) => void;\n};\n\nexport const PluginDetail = Util.composable<HTMLDivElement, PluginDetailProps>(\n (\n {\n plugin,\n scope,\n enabled,\n installing,\n updating,\n hasUpdate,\n installedVersionTag,\n selectedVersionTag,\n versions,\n dependencies,\n dependents,\n failure,\n onEnabledChange,\n onInstall,\n onInstallVersion,\n onNavigateToPlugin,\n onOpenSpec,\n onResolvePluginName,\n onUninstall,\n onUpdate,\n onVersionChange,\n ...props\n },\n forwardedRef,\n ) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const themeMode = Hooks.useThemeMode();\n const layout = ToolkitHooks.useLayout();\n // The gutters exist to hold the icon (col 1) and carousel nav (col 3); on a phone the fixed\n // 4rem floor on both left it with less width for the center content than the gutters themselves.\n const isMobile = layout.mode === 'mobile';\n const { key: slug, name, author, description, homePage, source, screenshots, icon: rawIcon } = plugin.meta.profile;\n const iconKey = rawIcon?.key ?? 'ph--circle--regular';\n const iconHue = rawIcon?.hue ?? 'neutral';\n const styles = getStyles(iconHue);\n\n const versionItems = useMemo(\n () =>\n (versions ?? []).map(({ version }) => ({\n value: version,\n label: installedVersionTag === version ? `${version} (${t('installed.label')})` : version,\n })),\n [versions, installedVersionTag, t],\n );\n\n const resolvedScreenshots = (screenshots ?? [])\n .map((entry) => (themeMode === 'dark' ? (entry.dark ?? entry.light) : (entry.light ?? entry.dark)))\n .filter((url): url is string => typeof url === 'string' && url.length > 0);\n\n return (\n <ScrollArea.Root {...Util.composableProps(props)} orientation='vertical' ref={forwardedRef}>\n <ScrollArea.Viewport>\n {/*\n * 3-column grid: [icon/prev | content/viewport | next].\n * Most sections occupy `col-start-2 col-span-2` so they stretch from\n * the centre column out to the trailing edge. The carousel uses\n * `display: contents` to flatten its children into this grid so\n * `Carousel.Previous` lands in col 1, `Carousel.Viewport` aligns\n * with the rest of the content in col 2, and `Carousel.Next` sits\n * in col 3.\n */}\n <Layout.Grid\n cols={isMobile ? ['2.5rem', 'minmax(0, 1fr)', '2.5rem'] : ['4rem', 'minmax(0, 1fr)', '4rem']}\n align='start'\n classNames='dx-document gap-x-4 p-4'\n >\n <Icon.Icon\n classNames={mx('row-start-1 p-1 rounded-md', isMobile ? 'size-8' : 'size-14', styles.bg, styles.fg)}\n icon={iconKey}\n />\n\n <Layout.Grid cols={['fill', 'min']} classNames='row-start-1 col-start-2 col-span-2 gap-x-3 w-full pt-1'>\n <Layout.Flex align='center' gap='sm'>\n <h2 className='text-xl'>{name}</h2>\n {failure && <PluginFailureBadge failure={failure} size='lg' />}\n </Layout.Flex>\n {onInstall ? (\n <Button.Root size='md' variant='primary' disabled={installing} onClick={onInstall}>\n {installing ? t('installing.label') : t('install.label')}\n </Button.Root>\n ) : (\n <Field.Root>\n <Input.Switch\n classNames='self-center'\n checked={enabled}\n onCheckedChange={({ checked }) => onEnabledChange?.(checked)}\n />\n </Field.Root>\n )}\n <Layout.Flex align='center' gap='xs' classNames='pt-0.5 text-sm text-fg-muted'>\n {slug}\n {author && (\n <span className='dx-tag dx-tag-inline' data-hue='info'>\n {author}\n </span>\n )}\n </Layout.Flex>\n </Layout.Grid>\n\n {scope && (\n <Section.Root>\n <Section.Heading title={t('plugin-scope.section.title')} />\n <Section.Body>{scope}</Section.Body>\n </Section.Root>\n )}\n\n {description && (\n <Section.Root>\n <Section.Heading title={t('description.label')} />\n <Section.Body>\n <MarkdownView classNames='text-fg-muted' content={description} />\n </Section.Body>\n </Section.Root>\n )}\n\n {resolvedScreenshots.length > 0 && (\n <Section.Root>\n <Section.Heading title={t('preview.label')} />\n <Section.Body>\n <Carousel.Root count={resolvedScreenshots.length}>\n <Carousel.ItemGroup>\n {resolvedScreenshots.map((src, index) => (\n <Carousel.Item key={src} index={index} src={src} alt={name} />\n ))}\n </Carousel.ItemGroup>\n <Carousel.IndicatorGroup />\n </Carousel.Root>\n </Section.Body>\n </Section.Root>\n )}\n\n <Section.Root>\n <Section.Heading title={t('resources.label')} />\n <Section.Body>\n <Layout.Flex gap='md' align='center'>\n {homePage && (\n <Typography.Link href={homePage} classNames='text-sm text-fg-muted'>\n {t('home-page.label')}\n <Icon.Icon\n icon='ph--arrow-square-out--regular'\n size='xs'\n classNames='ml-1 inline-block align-[-0.125em]'\n />\n </Typography.Link>\n )}\n\n {source && (\n <Typography.Link href={source} classNames='text-sm text-fg-muted'>\n {t('source.label')}\n <Icon.Icon\n icon='ph--arrow-square-out--regular'\n size='xs'\n classNames='ml-1 inline-block align-[-0.125em]'\n />\n </Typography.Link>\n )}\n\n {onOpenSpec && <Chip id={slug} name={t('open-spec.label')} onClick={onOpenSpec} />}\n </Layout.Flex>\n </Section.Body>\n </Section.Root>\n\n {dependencies && dependencies.length > 0 && (\n <Section.Root>\n <Section.Heading title={t('dependencies.label')} />\n <Section.Body>\n <Layout.Flex wrap gap='xs'>\n {dependencies.map((depId) => (\n <Chip\n key={depId}\n id={depId}\n name={onResolvePluginName?.(depId) ?? depId}\n onClick={onNavigateToPlugin}\n />\n ))}\n </Layout.Flex>\n </Section.Body>\n </Section.Root>\n )}\n\n {dependents && dependents.length > 0 && (\n <Section.Root>\n <Section.Heading title={t('dependents.label')} />\n <Section.Body>\n <Layout.Flex wrap gap='xs'>\n {dependents.map((dependentId) => (\n <Chip\n key={dependentId}\n id={dependentId}\n name={onResolvePluginName?.(dependentId) ?? dependentId}\n onClick={onNavigateToPlugin}\n />\n ))}\n </Layout.Flex>\n </Section.Body>\n </Section.Root>\n )}\n\n {versions && versions.length > 0 && (\n <Section.Root>\n <Section.Heading title={t('versions.label')} />\n <Section.Body>\n <Layout.Flex gap='sm' align='center'>\n <Select.Root\n items={versionItems}\n value={selectedVersionTag ? [selectedVersionTag] : []}\n onValueChange={({ value: [value] }) => value && onVersionChange?.(value)}\n >\n <Select.Trigger classNames='min-w-32' />\n <Select.Content>\n {versionItems.map((item) => (\n <Select.Item key={item.value} item={item} />\n ))}\n </Select.Content>\n </Select.Root>\n {onInstallVersion && (\n <Button.Root\n size='md'\n variant='primary'\n disabled={installing || selectedVersionTag === installedVersionTag}\n onClick={onInstallVersion}\n >\n {installing ? t('installing.label') : t('install-version.label')}\n </Button.Root>\n )}\n </Layout.Flex>\n </Section.Body>\n </Section.Root>\n )}\n\n {(onUninstall || (hasUpdate && onUpdate) || updating) && (\n <Layout.Flex gap='sm' classNames='col-start-2 col-span-2'>\n {updating ? (\n <Button.Root variant='primary' disabled>\n {t('updating.label')}\n </Button.Root>\n ) : hasUpdate && onUpdate ? (\n <Button.Root variant='primary' onClick={onUpdate}>\n {t('update.label')}\n </Button.Root>\n ) : null}\n {onUninstall && <Button.Root onClick={onUninstall}>{t('uninstall.label')}</Button.Root>}\n </Layout.Flex>\n )}\n </Layout.Grid>\n </ScrollArea.Viewport>\n </ScrollArea.Root>\n );\n },\n);\n\nPluginDetail.displayName = 'PluginDetail';\n\nconst SectionRoot = ({ children }: PropsWithChildren<{}>) => <>{children}</>;\n\nconst SectionHeading = ({ title }: { title: string }) => (\n <h2 className='col-start-2 col-span-2 pt-6 pb-2 uppercase text-sm font-medium text-fg-subtle'>{title}</h2>\n);\n\nconst SectionBody = ({ classNames, children }: Util.ThemedClassName<PropsWithChildren>) => (\n <Layout.Flex column gap='sm' classNames={['col-start-2', classNames]}>\n {children}\n </Layout.Flex>\n);\n\nconst Section = {\n Root: SectionRoot,\n Heading: SectionHeading,\n Body: SectionBody,\n};\n\nconst Chip = ({ id, name, onClick }: { id: string; name: string; onClick?: (pluginId: string) => void }) => (\n <Tag.Tag title={id} onClick={onClick ? () => onClick(id) : undefined} classNames='dx-hover'>\n {name}\n </Tag.Tag>\n);\n","//\n// Copyright 2025 DXOS.org\n//\n\nimport React, { type MouseEvent, useCallback, useMemo } from 'react';\n\nimport type * as Plugin from '@dxos/app-framework/Plugin';\nimport type * as PluginManager from '@dxos/app-framework/PluginManager';\nimport type * as ToolkitHooks from '@dxos/app-toolkit/Hooks';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Card from '@dxos/react-ui/Card';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Icon from '@dxos/react-ui/Icon';\nimport * as Input from '@dxos/react-ui/Input';\nimport * as Tag from '@dxos/react-ui/Tag';\nimport * as Typography from '@dxos/react-ui/Typography';\nimport { ACCENT_HUES } from '@dxos/ui-theme';\n\nimport { meta } from '#meta';\nimport { type RegistryTagType } from '#types';\n\nimport { PluginFailureBadge } from '../PluginFailureBadge/index.ts';\n\nexport type PluginItemProps = {\n plugin: Plugin.Plugin;\n /** Ids of plugins currently installed (loaded into the manager). */\n installed?: readonly string[];\n /** Ids of plugins whose install is in flight. */\n installing?: readonly string[];\n enabled?: readonly string[];\n /**\n * Derived tags (e.g. `registry`, `local`) to display alongside the plugin's own meta.tags.\n * Not persisted to plugin meta; computed per-render by the container.\n */\n extraTags?: readonly string[];\n /** Whether this device's answer for this plugin differs from the account's. */\n deviceOnly?: boolean;\n onClick?: (id: string, activation: ToolkitHooks.DetailActivation) => void;\n onChange?: (id: string, enabled: boolean) => void;\n /**\n * Install handler. When provided and the plugin is not installed, an Install button\n * is rendered in place of the enable switch.\n */\n onInstall?: (id: string) => void;\n /**\n * When true and plugin is installed, shows an Update button instead of the enable switch.\n */\n hasUpdate?: boolean;\n /** Called when the user clicks the Update button. */\n onUpdate?: (id: string) => void;\n /** Ids of plugins whose update is currently in flight. */\n updating?: readonly string[];\n hasSettings?: (id: string) => boolean;\n onSettings?: (id: string) => void;\n /**\n * Failure record for this plugin, if any. When present a warning badge is\n * rendered next to the plugin name; clicking it opens a popover with the\n * phase, reason, and error message.\n */\n failure?: PluginManager.PluginFailure;\n readOnly?: boolean;\n};\n\nexport const PluginItem = ({\n plugin,\n installed,\n installing,\n enabled = [],\n extraTags,\n deviceOnly,\n onClick,\n onChange,\n onInstall,\n hasUpdate,\n onUpdate,\n updating,\n hasSettings: hasSettingsProp,\n onSettings,\n failure,\n readOnly,\n}: PluginItemProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const { key: id, name, description, tags, icon: rawIcon } = plugin.meta.profile;\n const icon = rawIcon?.key ?? 'ph--circle--regular';\n // The manifest's hue is a free string; only a palette hue reaches the icon.\n const hue = ACCENT_HUES.find((candidate) => candidate === rawIcon?.hue);\n const displayTags = useMemo(() => {\n if (!extraTags || extraTags.length === 0) {\n return tags ?? [];\n }\n const set = new Set<string>(tags ?? []);\n for (const tag of extraTags) {\n set.add(tag);\n }\n return Array.from(set);\n }, [tags, extraTags]);\n const isEnabled = enabled.includes(id);\n const isInstalled = installed ? installed.includes(id) : true;\n const isInstalling = installing?.includes(id) ?? false;\n const isUpdating = updating?.includes(id) ?? false;\n const showInstallButton = !!onInstall && !isInstalled;\n const showUpdateButton = !!onUpdate && isInstalled && !!hasUpdate;\n const hasSettings = hasSettingsProp?.(id) ?? false;\n const titleId = `${id}-title`;\n const handleClick = useCallback(\n (event: MouseEvent) => onClick?.(id, { modified: event.metaKey || event.ctrlKey }),\n [id, onClick],\n );\n const handleSettings = useCallback(() => onSettings?.(id), [id, onSettings]);\n const handleInstall = useCallback(() => onInstall?.(id), [id, onInstall]);\n const handleUpdate = useCallback(() => onUpdate?.(id), [id, onUpdate]);\n\n return (\n <Card.Root role='listitem' aria-labelledby={titleId} data-testid={`pluginList.${id}`}>\n <Card.Tile icon={icon} hue={hue} aria-label={t('details.label')} onClick={handleClick} />\n <Card.Body>\n <Card.Header>\n <Card.Title id={titleId} truncate>\n {name ?? id}\n </Card.Title>\n {failure && <PluginFailureBadge failure={failure} />}\n {deviceOnly && (\n <Icon.Icon data-testid={`pluginList.${id}.deviceOnly`} icon='ph--monitor--regular' tone='muted' />\n )}\n </Card.Header>\n {description && (\n <Typography.Text tone='muted' lines={4}>\n {description}\n </Typography.Text>\n )}\n {displayTags.length > 0 && (\n <Button.Group>\n {displayTags.map((tag) => (\n <Tag.Tag key={tag} hue={tagColors[tag as RegistryTagType]}>\n {tag.toUpperCase()}\n </Tag.Tag>\n ))}\n </Button.Group>\n )}\n <Card.Footer justify='between'>\n <Button.Group>\n <Button.Root\n variant='ghost'\n iconOnly\n icon='ph--gear--regular'\n label={t('plugin-settings.label')}\n disabled={!hasSettings}\n onClick={handleSettings}\n />\n <Typography.Link asChild variant='neutral'>\n <button type='button' onClick={handleClick}>\n {t('details.label')}\n </button>\n </Typography.Link>\n </Button.Group>\n {isUpdating ? (\n <Button.Root variant='primary' disabled label={t('updating.label')} />\n ) : showUpdateButton ? (\n <Button.Root variant='primary' label={t('update.label')} onClick={handleUpdate} />\n ) : showInstallButton ? (\n <Button.Root\n variant='primary'\n disabled={isInstalling}\n label={isInstalling ? t('installing.label') : t('install.label')}\n onClick={handleInstall}\n />\n ) : (\n <Input.Switch\n aria-label={name ?? id}\n checked={isEnabled}\n disabled={readOnly}\n onCheckedChange={({ checked }) => onChange?.(id, checked)}\n />\n )}\n </Card.Footer>\n </Card.Body>\n </Card.Root>\n );\n};\n\nconst tagColors: Record<RegistryTagType, Tag.TagHue> = {\n new: 'rose',\n // Tier hues ramp green -> blue -> purple so the ordering reads without knowing the labels.\n beta: 'green',\n alpha: 'blue',\n labs: 'purple',\n popular: 'green',\n featured: 'pink',\n experimental: 'amber',\n registry: 'indigo',\n local: 'neutral',\n};\n","//\n// Copyright 2023 DXOS.org\n//\n\nimport React from 'react';\n\nimport type * as Plugin from '@dxos/app-framework/Plugin';\nimport type * as PluginManager from '@dxos/app-framework/PluginManager';\nimport * as Layout from '@dxos/react-ui/Layout';\n\nimport { PluginItem, type PluginItemProps } from './PluginItem.tsx';\n\nexport type PluginListProps = Omit<PluginItemProps, 'plugin' | 'extraTags' | 'hasUpdate' | 'failure'> & {\n plugins?: readonly Plugin.Plugin[];\n /**\n * Map from plugin id → extra tags to display (e.g. `registry`, `local`).\n * Computed by the container; not persisted to plugin meta.\n */\n extraTagsById?: Record<string, readonly string[]>;\n /**\n * Set of plugin ids for which a newer version is available in the catalog.\n * Causes each matching item to render an Update button instead of the enable switch.\n */\n updateAvailableIds?: ReadonlySet<string>;\n /**\n * Map from plugin id → most recent failure record. Used to render a warning\n * badge next to the plugin name. Sourced from `PluginManager.failed`.\n */\n failuresById?: Record<string, PluginManager.PluginFailure>;\n /** Ids whose value on this device differs from the account's. */\n deviceOnlyIds?: ReadonlySet<string>;\n};\n\nexport const PluginList = ({\n plugins = [],\n extraTagsById,\n updateAvailableIds,\n failuresById,\n deviceOnlyIds,\n ...props\n}: PluginListProps) => {\n return (\n <Layout.Container\n layout='row'\n columns='repeat(auto-fill, minmax(18rem, 1fr))'\n gap='lg'\n align='stretch'\n role='list'\n aria-label='plugins'\n >\n {plugins.map((plugin) => (\n <PluginItem\n key={plugin.meta.profile.key}\n plugin={plugin}\n extraTags={extraTagsById?.[plugin.meta.profile.key]}\n hasUpdate={updateAvailableIds?.has(plugin.meta.profile.key)}\n failure={failuresById?.[plugin.meta.profile.key]}\n deviceOnly={deviceOnlyIds?.has(plugin.meta.profile.key)}\n {...props}\n />\n ))}\n </Layout.Container>\n );\n};\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback } from 'react';\n\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as ToggleGroup from '@dxos/react-ui/ToggleGroup';\n\nimport { meta } from '#meta';\n\nexport type PluginScopeProps = {\n /** Whether this plugin's enabled state follows the account rather than being pinned here. */\n synced: boolean;\n /** Keep this plugin's state on this device. */\n onPin: () => void;\n /** Hand this plugin's state back to the account. */\n onUnpin: () => void;\n};\n\n/** Whether one plugin's enabled state follows the account or is pinned to this device. */\nexport const PluginScope = ({ synced, onPin, onUnpin }: PluginScopeProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const handleValueChange = useCallback(\n (value: string) => {\n if (value === 'shared' && !synced) {\n onUnpin();\n } else if (value === 'local' && synced) {\n onPin();\n }\n },\n [onPin, onUnpin, synced],\n );\n\n return (\n <ToggleGroup.Root type='single' value={synced ? 'shared' : 'local'} onValueChange={handleValueChange}>\n <ToggleGroup.Item\n value='shared'\n data-testid='pluginDetail.scope.shared'\n icon='ph--cloud-check--regular'\n label={t('plugin-scope.shared.label')}\n iconOnly\n />\n <ToggleGroup.Item\n value='local'\n data-testid='pluginDetail.scope.local'\n icon='ph--monitor--regular'\n label={t('plugin-scope.device-only.label')}\n iconOnly\n />\n </ToggleGroup.Root>\n );\n};\n\nPluginScope.displayName = 'PluginScope';\n","//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useState } from 'react';\n\nimport type * as AppSurface from '@dxos/app-toolkit/AppSurface';\nimport { log } from '@dxos/log';\nimport { Form } from '@dxos/react-ui-form';\nimport * as AlertDialog from '@dxos/react-ui/AlertDialog';\nimport * as Banner from '@dxos/react-ui/Banner';\nimport * as Button from '@dxos/react-ui/Button';\nimport * as Field from '@dxos/react-ui/Field';\nimport * as Hooks from '@dxos/react-ui/Hooks';\nimport * as Input from '@dxos/react-ui/Input';\n\nimport { meta } from '#meta';\nimport { RegistrySettingsSchema, type RegistrySettings as RegistrySettingsType } from '#types';\n\nexport type RegistrySettingsProps = AppSurface.SettingsProps<\n RegistrySettingsType,\n {\n activeDevPluginIds: readonly string[];\n onEnableDev: (url: string) => Promise<void>;\n onDisableDev: (id: string) => Promise<void>;\n /** Whether this device uses its own plugin set rather than the account's; `undefined` hides the section. */\n pluginScopeLocal?: boolean;\n onPluginScopeLocalChange?: (local: boolean) => void;\n }\n>;\n\n/**\n * Settings panel for `@dxos/plugin-registry`. The dev-plugin section lets a\n * plugin author point Composer at a local Vite dev server (defaults to\n * `localhost:3967`) and toggle the dev plugin on/off persistently — boot will\n * re-attach it on the next reload, surviving HMR-triggered reloads. If the\n * dev server is offline at boot, the toggle stays on and a warning is logged\n * (the manager's `failed` atom also surfaces a badge on the plugin list).\n *\n * The URL input and toggle are rendered as `Form.Field` action rows (not schema\n * fields): the input needs a dynamic disabled state and the toggle runs async\n * enable/disable side effects, neither of which a plain schema field expresses.\n */\nexport const RegistrySettings = ({\n settings,\n onSettingsChange,\n activeDevPluginIds,\n onEnableDev,\n onDisableDev,\n pluginScopeLocal,\n onPluginScopeLocalChange,\n scope,\n}: RegistrySettingsProps) => {\n const { t } = Hooks.useTranslation(meta.profile.key);\n const [rejoining, setRejoining] = useState(false);\n const [busy, setBusy] = useState(false);\n const enabled = !!settings.devPluginEnabled;\n const url = settings.devPluginUrl ?? '';\n const trimmedUrl = url.trim();\n const loadedDevId = activeDevPluginIds[0];\n\n const handleToggle = useCallback(async () => {\n if (busy || !onSettingsChange) {\n return;\n }\n setBusy(true);\n try {\n if (enabled && loadedDevId) {\n await onDisableDev(loadedDevId);\n onSettingsChange((current) => ({ ...current, devPluginEnabled: false }));\n } else if (enabled) {\n // Toggle is on but no dev plugin is currently loaded (boot-time load\n // failed or hasn't finished). Treat the click as \"turn it off.\"\n onSettingsChange((current) => ({ ...current, devPluginEnabled: false }));\n } else {\n if (!trimmedUrl) {\n return;\n }\n // Optimistically persist intent so the next reload retries even if\n // the page closes mid-load.\n onSettingsChange((current) => ({ ...current, devPluginEnabled: true }));\n try {\n await onEnableDev(trimmedUrl);\n } catch (error) {\n // Per product direction: leave the intent on, log the failure. The\n // user explicitly turns it off if they're done iterating.\n log.warn('dev plugin enable failed', { url: trimmedUrl, error });\n }\n }\n } finally {\n setBusy(false);\n }\n }, [busy, enabled, loadedDevId, onSettingsChange, onDisableDev, onEnableDev, trimmedUrl]);\n\n // Button label tracks the persisted intent, not the current load state, so\n // a transient \"intent on but not loaded\" combination still reads as\n // \"Disable Dev Plugin\" — clicking it turns the intent off cleanly.\n const buttonLabel = busy\n ? t('dev-plugin.busy.label')\n : enabled\n ? t('dev-plugin.disable.label')\n : t('dev-plugin.enable.label');\n\n return (\n <Form.Root variant='settings' readonly={!onSettingsChange} schema={RegistrySettingsSchema} values={settings}>\n <Form.Viewport scroll>\n <Form.Content>\n {pluginScopeLocal !== undefined && (\n <Form.FieldSet label={t('plugin-registry.label')} actions={scope}>\n <Form.Field label={t('plugin-scope.label')} description={t('plugin-scope.description')}>\n <Field.Root>\n <Input.Switch\n data-testid='registrySettings.pluginScope'\n // The scope is still worth showing without a handler; flipping it is not.\n disabled={!onPluginScopeLocalChange}\n checked={pluginScopeLocal}\n // Only rejoining asks: it replaces this device's choices with the account's.\n onCheckedChange={({ checked: local }) =>\n local ? onPluginScopeLocalChange?.(true) : setRejoining(true)\n }\n />\n </Field.Root>\n </Form.Field>\n </Form.FieldSet>\n )}\n <Form.FieldSet label={t('dev-plugin.section.title')}>\n <Banner.Root valence='neutral'>\n <Banner.Body>{t('dev-plugin.description')}</Banner.Body>\n </Banner.Root>\n <Form.Field label={t('dev-plugin.url.label')} description={t('dev-plugin.url.description')}>\n <Input.Root\n data-testid='registrySettings.devPluginUrl'\n disabled={!onSettingsChange || enabled || busy}\n value={url}\n onChange={(event) =>\n onSettingsChange?.((current) => ({ ...current, devPluginUrl: event.target.value }))\n }\n />\n </Form.Field>\n <Form.Field\n standalone\n label={t('dev-plugin.toggle.label')}\n description={t('dev-plugin.toggle.description')}\n >\n <Button.Root\n data-testid='registrySettings.devPluginToggle'\n variant={enabled ? undefined : 'primary'}\n disabled={!onSettingsChange || busy || (!enabled && !trimmedUrl)}\n onClick={() => void handleToggle()}\n >\n {buttonLabel}\n </Button.Root>\n </Form.Field>\n {enabled && !loadedDevId && !busy && (\n <Banner.Root valence='warning'>\n <Banner.Body>{t('dev-plugin.not-loaded.message')}</Banner.Body>\n </Banner.Root>\n )}\n </Form.FieldSet>\n </Form.Content>\n </Form.Viewport>\n <AlertDialog.Root open={rejoining} onOpenChange={({ open }) => setRejoining(open)}>\n <AlertDialog.Content>\n <AlertDialog.Body>\n <AlertDialog.Title>{t('plugin-scope.rejoin-dialog.title')}</AlertDialog.Title>\n <AlertDialog.Description>{t('plugin-scope.rejoin-dialog.description')}</AlertDialog.Description>\n </AlertDialog.Body>\n <AlertDialog.Footer>\n <div className='grow' />\n <AlertDialog.Cancel>{t('plugin-scope.rejoin-dialog.cancel.label')}</AlertDialog.Cancel>\n <AlertDialog.Action\n data-testid='registrySettings.pluginScope.confirm'\n variant='primary'\n onClick={() => {\n onPluginScopeLocalChange?.(false);\n setRejoining(false);\n }}\n >\n {t('plugin-scope.rejoin-dialog.confirm.label')}\n </AlertDialog.Action>\n </AlertDialog.Footer>\n </AlertDialog.Content>\n </AlertDialog.Root>\n </Form.Root>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
export type RegistryCategoryArticleProps = {
|
|
3
|
+
contextId: string;
|
|
3
4
|
category: string;
|
|
4
5
|
};
|
|
5
6
|
/**
|
|
@@ -7,5 +8,5 @@ export type RegistryCategoryArticleProps = {
|
|
|
7
8
|
* `usePluginManager` + `useRegistryPlugins` + `useAutoTags` wiring shared by every category surface,
|
|
8
9
|
* none of which can live in a surface's `props` mapper.
|
|
9
10
|
*/
|
|
10
|
-
export declare const RegistryCategoryArticle: ({ category }: RegistryCategoryArticleProps) => React.JSX.Element;
|
|
11
|
+
export declare const RegistryCategoryArticle: ({ contextId, category }: RegistryCategoryArticleProps) => React.JSX.Element;
|
|
11
12
|
//# sourceMappingURL=RegistryCategoryArticle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegistryCategoryArticle.d.ts","sourceRoot":"","sources":["../../../../src/capabilities/RegistryCategoryArticle.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAkB,MAAM,OAAO,CAAC;AA0BvC,MAAM,MAAM,4BAA4B,GAAG;IACzC,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"RegistryCategoryArticle.d.ts","sourceRoot":"","sources":["../../../../src/capabilities/RegistryCategoryArticle.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAkB,MAAM,OAAO,CAAC;AA0BvC,MAAM,MAAM,4BAA4B,GAAG;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,4BAA6B,4BAA4B,sBAgB5F,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PluginFailureBadge.d.ts","sourceRoot":"","sources":["../../../../../src/components/PluginFailureBadge/PluginFailureBadge.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAE7D,OAAO,KAAK,KAAK,aAAa,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"PluginFailureBadge.d.ts","sourceRoot":"","sources":["../../../../../src/components/PluginFailureBadge/PluginFailureBadge.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAE,KAAK,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAE7D,OAAO,KAAK,KAAK,aAAa,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAOhD,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,aAAa,CAAC,aAAa,CAAC;IACrC,gCAAgC;IAChC,IAAI,CAAC,EAAE,wBAAwB,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC;CACjE,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,sBAAuB,uBAAuB,sBAiC5E,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type * as Plugin from '@dxos/app-framework/Plugin';
|
|
3
3
|
import type * as PluginManager from '@dxos/app-framework/PluginManager';
|
|
4
|
+
import type * as ToolkitHooks from '@dxos/app-toolkit/Hooks';
|
|
4
5
|
export type PluginItemProps = {
|
|
5
6
|
plugin: Plugin.Plugin;
|
|
6
7
|
/** Ids of plugins currently installed (loaded into the manager). */
|
|
@@ -15,7 +16,7 @@ export type PluginItemProps = {
|
|
|
15
16
|
extraTags?: readonly string[];
|
|
16
17
|
/** Whether this device's answer for this plugin differs from the account's. */
|
|
17
18
|
deviceOnly?: boolean;
|
|
18
|
-
onClick?: (id: string) => void;
|
|
19
|
+
onClick?: (id: string, activation: ToolkitHooks.DetailActivation) => void;
|
|
19
20
|
onChange?: (id: string, enabled: boolean) => void;
|
|
20
21
|
/**
|
|
21
22
|
* Install handler. When provided and the plugin is not installed, an Install button
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PluginItem.d.ts","sourceRoot":"","sources":["../../../../../src/components/PluginList/PluginItem.tsx"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"PluginItem.d.ts","sourceRoot":"","sources":["../../../../../src/components/PluginList/PluginItem.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAgD,MAAM,OAAO,CAAC;AAErE,OAAO,KAAK,KAAK,MAAM,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,KAAK,aAAa,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,KAAK,YAAY,MAAM,yBAAyB,CAAC;AAe7D,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;IACtB,oEAAoE;IACpE,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,iDAAiD;IACjD,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,+EAA+E;IAC/E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,YAAY,CAAC,gBAAgB,KAAK,IAAI,CAAC;IAC1E,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,UAAU,iMAiBpB,eAAe,sBAkGjB,CAAC"}
|
|
@@ -3,8 +3,7 @@ import '@dxos/react-ui/theme.css';
|
|
|
3
3
|
import type * as Plugin from '@dxos/app-framework/Plugin';
|
|
4
4
|
import { type PluginListProps } from '#components';
|
|
5
5
|
export type BaseRegistryArticleProps = {
|
|
6
|
-
|
|
7
|
-
id: string;
|
|
6
|
+
contextId: string;
|
|
8
7
|
/** Plugins to display, pre-sorted by the caller. */
|
|
9
8
|
plugins: readonly Plugin.Plugin[];
|
|
10
9
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseRegistryArticle.d.ts","sourceRoot":"","sources":["../../../../../src/containers/BaseRegistryArticle/BaseRegistryArticle.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAkC,MAAM,OAAO,CAAC;AAI9E,OAAO,0BAA0B,CAAC;AAClC,OAAO,KAAK,KAAK,MAAM,MAAM,4BAA4B,CAAC;AAe1D,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAW/D,MAAM,MAAM,wBAAwB,GAAG;IACrC,
|
|
1
|
+
{"version":3,"file":"BaseRegistryArticle.d.ts","sourceRoot":"","sources":["../../../../../src/containers/BaseRegistryArticle/BaseRegistryArticle.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,KAAK,SAAS,EAAkC,MAAM,OAAO,CAAC;AAI9E,OAAO,0BAA0B,CAAC;AAClC,OAAO,KAAK,KAAK,MAAM,MAAM,4BAA4B,CAAC;AAe1D,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAW/D,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,OAAO,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC;IAClC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB,GAAG,IAAI,CACN,eAAe,EACb,WAAW,GACX,YAAY,GACZ,UAAU,GACV,oBAAoB,GACpB,eAAe,GACf,cAAc,GACd,eAAe,GACf,WAAW,GACX,UAAU,CACb,CAAC;AAEF,eAAO,MAAM,mBAAmB;;6GAyH/B,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
export type PublicRegistryArticleProps = {
|
|
3
|
-
|
|
3
|
+
contextId: string;
|
|
4
4
|
};
|
|
5
5
|
export declare const PublicRegistryArticle: React.ForwardRefExoticComponent<Omit<PublicRegistryArticleProps, "className"> & {
|
|
6
6
|
classNames?: import("@dxos/ui-types").ClassNameValue;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublicRegistryArticle.d.ts","sourceRoot":"","sources":["../../../../../src/containers/PublicRegistryArticle/PublicRegistryArticle.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAoD,MAAM,OAAO,CAAC;AA+CzE,MAAM,MAAM,0BAA0B,GAAG;IACvC,
|
|
1
|
+
{"version":3,"file":"PublicRegistryArticle.d.ts","sourceRoot":"","sources":["../../../../../src/containers/PublicRegistryArticle/PublicRegistryArticle.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAoD,MAAM,OAAO,CAAC;AA+CzE,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,qBAAqB;;6GAoJjC,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type * as Plugin from '@dxos/app-framework/Plugin';
|
|
3
3
|
export type RegistryArticleProps = {
|
|
4
|
-
|
|
4
|
+
contextId: string;
|
|
5
5
|
plugins: Plugin.Plugin[];
|
|
6
6
|
/**
|
|
7
7
|
* Map from plugin id → display-only tags (e.g. `registry`, `local`) computed by the caller.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RegistryArticle.d.ts","sourceRoot":"","sources":["../../../../../src/containers/RegistryArticle/RegistryArticle.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,KAAK,MAAM,MAAM,4BAA4B,CAAC;AAU1D,MAAM,MAAM,oBAAoB,GAAG;IACjC,
|
|
1
|
+
{"version":3,"file":"RegistryArticle.d.ts","sourceRoot":"","sources":["../../../../../src/containers/RegistryArticle/RegistryArticle.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,KAAK,MAAM,MAAM,4BAA4B,CAAC;AAU1D,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IACzB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;CACnD,CAAC;AAEF,eAAO,MAAM,eAAe;;6GAyB3B,CAAC"}
|