PhoenixKitDashboards.Registry (PhoenixKitDashboards v0.1.0)

Copy Markdown View Source

Discovers and caches the widget catalog.

The catalog is the union of every PhoenixKit module that defines phoenix_kit_widgets/0 (see PhoenixKitDashboards.Widget for the contract). This module is one such provider — its built-in widgets (note, clock, module-stats) are exposed through the same phoenix_kit_widgets/0 entry point as any other module, so there is no special-cased "built-in" path.

Discovery is convention-based — it queries PhoenixKit.ModuleRegistry at runtime and calls phoenix_kit_widgets/0 on any module that exports it (always including PhoenixKitDashboards itself, so the built-ins are available even before/without ModuleRegistry discovery). No new core PhoenixKit.Module callback is required, so this ships independently of a core release. (If the contract proves load-bearing, it can later be promoted into the PhoenixKit.Module behaviour.)

The result is memoized in :persistent_term, mirroring how core's ModuleRegistry caches tabs and permissions. Call refresh/0 after modules are toggled to rebuild.

Summary

Functions

The full widget catalog, keyed by widget key.

Look up a single widget type by key.

List all catalog widgets, sorted by category then name.

Catalog widgets visible to a given scope.

Rebuild the catalog from every discovered widget provider and re-cache it.

Whether one widget type is visible to a scope — the same gate list_for_scope/1 applies to the catalog. The render path uses it too, so a placed widget stops rendering (and refreshing) when its module is disabled or the viewer's scope lacks the module permission — placing a widget must not outlive the gate that offered it. nil scope skips the permission half (module enablement still applies); a widget with no module_key is always visible.

Functions

catalog()

@spec catalog() :: %{required(String.t()) => PhoenixKitDashboards.Widget.t()}

The full widget catalog, keyed by widget key.

Memoized in :persistent_term; first call builds it.

get(key)

@spec get(String.t()) :: PhoenixKitDashboards.Widget.t() | nil

Look up a single widget type by key.

list()

@spec list() :: [PhoenixKitDashboards.Widget.t()]

List all catalog widgets, sorted by category then name.

list_for_scope(scope)

@spec list_for_scope(scope :: term() | nil) :: [PhoenixKitDashboards.Widget.t()]

Catalog widgets visible to a given scope.

Filters out widgets whose owning module is disabled or whose module_key permission the scope lacks. Built-in widgets (no module_key) are always visible. Pass nil to skip filtering (e.g. system/internal callers).

refresh()

@spec refresh() :: %{required(String.t()) => PhoenixKitDashboards.Widget.t()}

Rebuild the catalog from every discovered widget provider and re-cache it.

visible_for_scope?(widget, scope)

@spec visible_for_scope?(PhoenixKitDashboards.Widget.t(), scope :: term() | nil) ::
  boolean()

Whether one widget type is visible to a scope — the same gate list_for_scope/1 applies to the catalog. The render path uses it too, so a placed widget stops rendering (and refreshing) when its module is disabled or the viewer's scope lacks the module permission — placing a widget must not outlive the gate that offered it. nil scope skips the permission half (module enablement still applies); a widget with no module_key is always visible.