From b931a24d5ee8b4799f7067ef394e8668e60c2ae0 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Mon, 17 Feb 2025 17:21:23 +0100 Subject: [PATCH] Types --- packages/builder/src/helpers/components.ts | 77 +++++++++++++--------- packages/frontend-core/src/constants.ts | 5 +- packages/types/src/ui/components/index.ts | 15 +++++ packages/types/src/ui/stores/preview.ts | 1 - 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/packages/builder/src/helpers/components.ts b/packages/builder/src/helpers/components.ts index f03551076e..916e518b3b 100644 --- a/packages/builder/src/helpers/components.ts +++ b/packages/builder/src/helpers/components.ts @@ -8,28 +8,32 @@ import { } from "@budibase/string-templates" import { capitalise } from "@/helpers" import { Constants } from "@budibase/frontend-core" -import { ScreenProps } from "@budibase/types" +import { Component, ComponentContext } from "@budibase/types" const { ContextScopes } = Constants /** * Recursively searches for a specific component ID */ -export const findComponent = (rootComponent: ScreenProps, id: string) => { +export const findComponent = (rootComponent: Component, id: string) => { return searchComponentTree(rootComponent, comp => comp._id === id) } /** * Recursively searches for a specific component type */ -export const findComponentType = (rootComponent, type) => { +export const findComponentType = (rootComponent: Component, type: string) => { return searchComponentTree(rootComponent, comp => comp._component === type) } /** * Recursively searches for the parent component of a specific component ID */ -export const findComponentParent = (rootComponent, id, parentComponent) => { +export const findComponentParent = ( + rootComponent: Component, + id: string, + parentComponent: Component +): Component | null => { if (!rootComponent || !id) { return null } @@ -52,7 +56,11 @@ export const findComponentParent = (rootComponent, id, parentComponent) => { * Recursively searches for a specific component ID and records the component * path to this component */ -export const findComponentPath = (rootComponent, id, path = []) => { +export const findComponentPath = ( + rootComponent: Component, + id: string, + path: Component[] = [] +): Component[] => { if (!rootComponent || !id) { return [] } @@ -76,11 +84,14 @@ export const findComponentPath = (rootComponent, id, path = []) => { * Recurses through the component tree and finds all components which match * a certain selector */ -export const findAllMatchingComponents = (rootComponent, selector) => { +export const findAllMatchingComponents = ( + rootComponent: Component, + selector: (component: Component) => boolean +) => { if (!rootComponent || !selector) { return [] } - let components = [] + let components: Component[] = [] if (rootComponent._children) { rootComponent._children.forEach(child => { components = [ @@ -98,7 +109,7 @@ export const findAllMatchingComponents = (rootComponent, selector) => { /** * Recurses through the component tree and finds all components. */ -export const findAllComponents = rootComponent => { +export const findAllComponents = (rootComponent: Component) => { return findAllMatchingComponents(rootComponent, () => true) } @@ -106,9 +117,9 @@ export const findAllComponents = rootComponent => { * Finds the closest parent component which matches certain criteria */ export const findClosestMatchingComponent = ( - rootComponent, - componentId, - selector + rootComponent: Component, + componentId: string, + selector: (component: Component) => boolean ) => { if (!selector) { return null @@ -126,7 +137,10 @@ export const findClosestMatchingComponent = ( * Recurses through a component tree evaluating a matching function against * components until a match is found */ -const searchComponentTree = (rootComponent, matchComponent) => { +const searchComponentTree = ( + rootComponent: Component, + matchComponent: (component: Component) => boolean +): Component | null => { if (!rootComponent || !matchComponent) { return null } @@ -151,15 +165,18 @@ const searchComponentTree = (rootComponent, matchComponent) => { * This mutates the object in place. * @param component the component to randomise */ -export const makeComponentUnique = component => { +export const makeComponentUnique = (component: Component) => { if (!component) { return } // Generate a full set of component ID replacements in this tree - const idReplacements = [] - const generateIdReplacements = (component, replacements) => { - const oldId = component._id + const idReplacements: [string, string][] = [] + const generateIdReplacements = ( + component: Component, + replacements: [string, string][] + ) => { + const oldId = component._id! const newId = Helpers.uuid() replacements.push([oldId, newId]) component._children?.forEach(x => generateIdReplacements(x, replacements)) @@ -183,9 +200,9 @@ export const makeComponentUnique = component => { let js = decodeJSBinding(sanitizedBinding) if (js != null) { // Replace ID inside JS binding - idReplacements.forEach(([oldId, newId]) => { + for (const [oldId, newId] of idReplacements) { js = js.replace(new RegExp(oldId, "g"), newId) - }) + } // Create new valid JS binding let newBinding = encodeJSBinding(js) @@ -205,7 +222,7 @@ export const makeComponentUnique = component => { return JSON.parse(definition) } -export const getComponentText = component => { +export const getComponentText = (component: Component) => { if (component == null) { return "" } @@ -219,7 +236,7 @@ export const getComponentText = component => { return capitalise(type) } -export const getComponentName = component => { +export const getComponentName = (component: Component) => { if (component == null) { return "" } @@ -230,9 +247,9 @@ export const getComponentName = component => { } // Gets all contexts exposed by a certain component type, including actions -export const getComponentContexts = component => { +export const getComponentContexts = (component: string) => { const def = componentStore.getDefinition(component) - let contexts = [] + let contexts: ComponentContext[] = [] if (def?.context) { contexts = Array.isArray(def.context) ? [...def.context] : [def.context] } @@ -252,9 +269,9 @@ export const getComponentContexts = component => { * Recurses through the component tree and builds a tree of contexts provided * by components. */ -export const buildContextTree = ( - rootComponent, - tree = { root: [] }, +const buildContextTree = ( + rootComponent: Component, + tree: Record = { root: [] }, currentBranch = "root" ) => { // Sanity check @@ -265,12 +282,12 @@ export const buildContextTree = ( // Process this component's contexts const contexts = getComponentContexts(rootComponent._component) if (contexts.length) { - tree[currentBranch].push(rootComponent._id) + tree[currentBranch].push(rootComponent._id!) // If we provide local context, start a new branch for our children if (contexts.some(context => context.scope === ContextScopes.Local)) { - currentBranch = rootComponent._id - tree[rootComponent._id] = [] + currentBranch = rootComponent._id! + tree[rootComponent._id!] = [] } } @@ -300,9 +317,9 @@ export const buildContextTreeLookupMap = rootComponent => { } // Get a flat list of ids for all descendants of a component -export const getChildIdsForComponent = component => { +export const getChildIdsForComponent = (component: Component): string[] => { return [ - component._id, + component._id!, ...(component?._children ?? []).map(getChildIdsForComponent).flat(1), ] } diff --git a/packages/frontend-core/src/constants.ts b/packages/frontend-core/src/constants.ts index 907d91825f..28210117ba 100644 --- a/packages/frontend-core/src/constants.ts +++ b/packages/frontend-core/src/constants.ts @@ -112,10 +112,7 @@ export const EventPublishType = { ENV_VAR_UPGRADE_PANEL_OPENED: "environment_variable_upgrade_panel_opened", } -export const ContextScopes = { - Local: "local", - Global: "global", -} +export { ComponentContextScopes } from "@budibase/types" export const TypeIconMap = { [FieldType.STRING]: "Text", diff --git a/packages/types/src/ui/components/index.ts b/packages/types/src/ui/components/index.ts index f477ed2bd3..4be203151e 100644 --- a/packages/types/src/ui/components/index.ts +++ b/packages/types/src/ui/components/index.ts @@ -28,6 +28,8 @@ export interface ComponentDefinition { width: number height: number } + context?: ComponentContext | ComponentContext[] + actions?: (string | any)[] } export type DependsOnComponentSetting = @@ -56,3 +58,16 @@ export interface ComponentSetting { self: boolean } } + +export interface ComponentContext { + type: ComponentContextType + scope: ComponentContextScopes + actions: any[] +} + +export type ComponentContextType = "action" + +export const enum ComponentContextScopes { + Local = "local", + Global = "global", +} diff --git a/packages/types/src/ui/stores/preview.ts b/packages/types/src/ui/stores/preview.ts index d9f5f2ac46..4d09366ff5 100644 --- a/packages/types/src/ui/stores/preview.ts +++ b/packages/types/src/ui/stores/preview.ts @@ -1,2 +1 @@ export type PreviewDevice = "desktop" | "tablet" | "mobile" -export type ComponentContext = Record