11<template >
2- <div class =" CoreTabs" >
2+ <div ref = " rootInstance " class =" CoreTabs" >
33 <nav
44 class =" tabSelector horizontal"
55 data-writer-cage
@@ -26,6 +26,14 @@ import {
2626 buttonShadow ,
2727 cssClasses ,
2828} from " @/renderer/sharedStyleFields" ;
29+ import { useFormValueBroker } from " @/renderer/useFormValueBroker" ;
30+
31+ const tabChangeHandlerStub = `
32+ def tab_change_handler(state, payload):
33+
34+ # The payload contains the name of the newly activated tab
35+
36+ state["active_tab"] = payload ` ;
2937
3038const description =
3139 " A container component for organising and displaying Tab components in a tabbed interface." ;
@@ -36,6 +44,14 @@ export default {
3644 description ,
3745 category: " Layout" ,
3846 allowedChildrenTypes: [" tab" , " repeater" ],
47+ events: {
48+ " wf-tab-change" : {
49+ desc: " Sent when the active tab changes." ,
50+ stub: tabChangeHandlerStub .trim (),
51+ eventPayloadExample: " Tab Name" ,
52+ bindable: true ,
53+ },
54+ },
3955 fields: {
4056 accentColor ,
4157 primaryTextColor ,
@@ -52,11 +68,76 @@ export default {
5268};
5369 </script >
5470<script setup lang="ts">
55- import { inject } from " vue" ;
71+ import { ComponentPublicInstance , inject , onMounted , ref , watch } from " vue" ;
72+ import { useEvaluator } from " @/renderer/useEvaluator" ;
5673import injectionKeys from " @/injectionKeys" ;
57-
74+ const rootInstance = ref <ComponentPublicInstance | null >(null );
75+ const wf = inject (injectionKeys .core );
76+ const instancePath = inject (injectionKeys .instancePath );
5877const instanceData = inject (injectionKeys .instanceData );
59- instanceData .at (- 1 ).value = { activeTab: undefined };
78+ const containerState = instanceData .at (- 1 );
79+ const { isComponentVisible } = useEvaluator (wf );
80+
81+ const { formValue, handleInput } = useFormValueBroker (
82+ wf ,
83+ instancePath ,
84+ rootInstance ,
85+ );
86+
87+ containerState .value = {
88+ activeTab: undefined ,
89+ activeTabName: formValue .value ,
90+ tabs: [],
91+ };
92+
93+ watch (
94+ () => containerState .value ?.activeTabName ,
95+ (activeTabName ) => {
96+ if (! rootInstance .value ) return ;
97+ if (activeTabName === formValue .value ) return ;
98+ handleInput (activeTabName , " wf-tab-change" );
99+ },
100+ );
101+
102+ watch (formValue , (newTabName ) => {
103+ if (newTabName === containerState .value .activeTabName ) return ;
104+ if (! containerState .value .tabs ?.length ) return ;
105+
106+ const visibleTabs = containerState .value .tabs .filter ((t ) =>
107+ isComponentVisible (t .componentId , t .instancePath ),
108+ );
109+ if (! visibleTabs .length ) return ;
110+
111+ let tabToActivate = visibleTabs .find ((t ) => t .name === newTabName );
112+
113+ if (! tabToActivate ) {
114+ const currentActiveInState = visibleTabs .find (
115+ (t ) => t .name === containerState .value .activeTabName ,
116+ );
117+ tabToActivate = currentActiveInState ?? visibleTabs [0 ];
118+ }
119+
120+ containerState .value .activeTab = tabToActivate .instancePath ;
121+ containerState .value .activeTabName = tabToActivate .name ;
122+ });
123+
124+ onMounted (() => {
125+ if (containerState .value .activeTab ) return ;
126+ if (! containerState .value .tabs ) return ;
127+
128+ const visibleTabs = containerState .value .tabs .filter ((t ) =>
129+ isComponentVisible (t .componentId , t .instancePath ),
130+ );
131+ if (visibleTabs .length === 0 ) return ;
132+
133+ const initialActiveTabName = containerState .value .activeTabName ;
134+ const tabToActivate =
135+ visibleTabs .find ((t ) => t .name === initialActiveTabName ) ??
136+ visibleTabs [0 ];
137+
138+ containerState .value .activeTab = tabToActivate .instancePath ;
139+ containerState .value .activeTabName = tabToActivate .name ;
140+ });
60141 </script >
61142
62143<style scoped>
0 commit comments