diff --git a/app/components/DocumentListItem.tsx b/app/components/DocumentListItem.tsx index a6a66dce49..c7970801aa 100644 --- a/app/components/DocumentListItem.tsx +++ b/app/components/DocumentListItem.tsx @@ -101,11 +101,10 @@ function DocumentListItem( return ( { } return ( - + = ({ }); return ( - + diff --git a/app/components/Sidebar/components/StarredLink.tsx b/app/components/Sidebar/components/StarredLink.tsx index 6e88c1dc08..7ff043d841 100644 --- a/app/components/Sidebar/components/StarredLink.tsx +++ b/app/components/Sidebar/components/StarredLink.tsx @@ -103,7 +103,7 @@ const StarredDocumentLink = observer(function StarredDocumentLink({ return ( diff --git a/app/components/Star.tsx b/app/components/Star.tsx index 15b72f9b9d..7e64bbd7d2 100644 --- a/app/components/Star.tsx +++ b/app/components/Star.tsx @@ -37,8 +37,9 @@ function Star({ size, document, collection, color, ...rest }: Props) { return ( !!m + ), }} > ( undefined ); +interface ActionContextProviderValue { + /** Models to add to the active models context for this subtree. */ + activeModels?: Model[]; + isMenu?: boolean; + isCommandBar?: boolean; + isButton?: boolean; + sidebarContext?: SidebarContextType; + event?: Event; +} + type ActionContextProviderProps = { children: ReactNode; - value?: Partial; + value?: ActionContextProviderValue; }; /** @@ -23,15 +34,15 @@ type ActionContextProviderProps = { * * @example * ```tsx - * // Override context for a command bar - * - * + * // Override active models for a collection menu + * + * * * * // Nested overrides - * + * * - * + * * * * @@ -45,6 +56,7 @@ export const ActionContextProvider = observer(function ActionContextProvider_({ const stores = useStores(); const { t } = useTranslation(); const location = useLocation(); + const { activeModels: valueModels, ...overrides } = value; // Create the base context if we don't have a parent context const baseContext: ActionContextType = parentContext ?? { @@ -56,7 +68,6 @@ export const ActionContextProvider = observer(function ActionContextProvider_({ activeCollectionId: stores.ui.activeCollectionId ?? undefined, activeDocumentId: stores.ui.activeDocumentId ?? undefined, - // New API getActiveModels: ( modelClass: new (...args: any[]) => T ): T[] => stores.ui.getActiveModels(modelClass), @@ -83,33 +94,18 @@ export const ActionContextProvider = observer(function ActionContextProvider_({ t, }; - // Merge the parent context with the provided overrides - const activeCollectionId = - value.activeCollectionId ?? baseContext.activeCollectionId; - const activeDocumentId = - value.activeDocumentId ?? baseContext.activeDocumentId; - - const getActiveModels = ( - modelClass: new (...args: any[]) => T - ): T[] => { - // @ts-expect-error modelName - if (activeCollectionId && modelClass.modelName === "Collection") { - const model = stores.collections.get(activeCollectionId); - if (model) { - return [model as unknown as T]; - } - } - - // @ts-expect-error modelName - if (activeDocumentId && modelClass.modelName === "Document") { - const model = stores.documents.get(activeDocumentId); - if (model) { - return [model as unknown as T]; - } - } - - return baseContext.getActiveModels(modelClass); - }; + // Override model accessors when models are provided in value + const getActiveModels = + valueModels && valueModels.length > 0 + ? (modelClass: new (...args: any[]) => T): T[] => { + const matching = valueModels.filter( + (model): model is T => model instanceof modelClass + ); + return matching.length > 0 + ? matching + : baseContext.getActiveModels(modelClass); + } + : baseContext.getActiveModels; const getActiveModel = ( modelClass: new (...args: any[]) => T @@ -122,12 +118,34 @@ export const ActionContextProvider = observer(function ActionContextProvider_({ .map((node) => stores.policies.get(node.id)) .filter((policy): policy is Policy => policy !== undefined); + const allActiveModels = + valueModels && valueModels.length > 0 + ? new Set([...baseContext.activeModels, ...valueModels]) + : baseContext.activeModels; + + const isModelActive = (model: Model): boolean => allActiveModels.has(model); + + // Derive legacy IDs from value models, falling back to base context + const activeCollectionId = + valueModels?.find( + (m) => (m.constructor as typeof Model).modelName === "Collection" + )?.id ?? baseContext.activeCollectionId; + + const activeDocumentId = + valueModels?.find( + (m) => (m.constructor as typeof Model).modelName === "Document" + )?.id ?? baseContext.activeDocumentId; + const contextValue: ActionContextType = { ...baseContext, - ...value, + ...overrides, + activeCollectionId, + activeDocumentId, getActiveModels, getActiveModel, getActivePolicies, + isModelActive, + activeModels: allActiveModels, }; return ( diff --git a/app/menus/CollectionMenu.tsx b/app/menus/CollectionMenu.tsx index b7b3134b69..e152e32285 100644 --- a/app/menus/CollectionMenu.tsx +++ b/app/menus/CollectionMenu.tsx @@ -53,7 +53,7 @@ function CollectionMenu({ }); return ( - + +