This example demonstrates a component-based JSON transformation system with visual tree editor, 40+ transforms, recipe export/import, and template mode for arrays.
Key Architecture: All components register with a shared desk using VueAirport's useCheckIn. Child components access shared state directly through desk registration, enabling clean separation of concerns.
[
{
"name": "marina abramović",
"age": 20,
"active": false,
"city": "marseille",
"address": {
"street": "100 main st",
"zip": "10000",
"custom": {
"info": "custom info 0",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović0@example.com",
"phone": "+33 1 10 10 10 10"
},
{
"name": "pina cunningham",
"age": 21,
"active": true,
"city": "paris",
"address": {
"street": "101 elm st",
"zip": "10001",
"custom": {
"info": "custom info 1",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1951-02-02T00:00:00.000Z",
"email": "pina.cunningham1@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 22,
"active": true,
"city": "lyon",
"address": {
"street": "102 oak ave",
"zip": "10002"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1952-03-03T00:00:00.000Z",
"email": "laurie.de keersmaeker2@example.com",
"phone": "+33 3 12 12 12 12"
},
{
"name": "romeo bausch",
"age": 23,
"active": false,
"city": "toulouse",
"address": {
"street": "103 maple dr",
"zip": "10003"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1953-04-04T00:00:00.000Z",
"email": "romeo.bausch3@example.com"
},
{
"name": "anne Teresa childs",
"age": 24,
"active": true,
"city": "nice",
"address": {
"street": "104 pine rd",
"zip": "10004"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1954-05-05T00:00:00.000Z",
"email": "anne Teresa.childs4@example.com",
"phone": "+33 5 14 14 14 14"
},
{
"name": "william forsythe",
"age": 25,
"active": true,
"city": "nantes",
"address": {
"street": "105 cedar ln",
"zip": "10005",
"custom": {
"info": "custom info 5",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe5@example.com"
},
{
"name": "robert anderson",
"age": 26,
"active": false,
"city": "strasbourg",
"address": {
"street": "106 birch way",
"zip": "10006",
"custom": {
"info": "custom info 6",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1956-07-07T00:00:00.000Z",
"email": "robert.anderson6@example.com",
"phone": "+33 7 16 16 16 16"
},
{
"name": "merce pite",
"age": 27,
"active": true,
"city": "montpellier",
"address": {
"street": "107 ash ct",
"zip": "10007"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1957-08-08T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 28,
"active": true,
"city": "bordeaux",
"address": {
"street": "108 main st",
"zip": "10008"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1958-09-09T00:00:00.000Z",
"phone": "+33 9 18 18 18 18"
},
{
"name": "crystal castellucci",
"age": 29,
"active": false,
"city": "lille",
"address": {
"street": "109 elm st",
"zip": "10009"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1959-10-10T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 30,
"active": true,
"city": "marseille",
"address": {
"street": "110 oak ave",
"zip": "10010",
"custom": {
"info": "custom info 10",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović10@example.com",
"phone": "+33 2 20 20 20 20"
},
{
"name": "pina cunningham",
"age": 31,
"active": true,
"city": "paris",
"address": {
"street": "111 maple dr",
"zip": "10011",
"custom": {
"info": "custom info 11",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1961-12-12T00:00:00.000Z",
"email": "pina.cunningham11@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 32,
"active": false,
"city": "lyon",
"address": {
"street": "112 pine rd",
"zip": "10012"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1962-01-13T00:00:00.000Z",
"email": "laurie.de keersmaeker12@example.com",
"phone": "+33 4 22 22 22 22"
},
{
"name": "romeo bausch",
"age": 33,
"active": true,
"city": "toulouse",
"address": {
"street": "113 cedar ln",
"zip": "10013"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1963-02-14T00:00:00.000Z",
"email": "romeo.bausch13@example.com"
},
{
"name": "anne Teresa childs",
"age": 34,
"active": true,
"city": "nice",
"address": {
"street": "114 birch way",
"zip": "10014"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1964-03-15T00:00:00.000Z",
"email": "anne Teresa.childs14@example.com",
"phone": "+33 6 24 24 24 24"
},
{
"name": "william forsythe",
"age": 35,
"active": false,
"city": "nantes",
"address": {
"street": "115 ash ct",
"zip": "10015",
"custom": {
"info": "custom info 15",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe15@example.com"
},
{
"name": "robert anderson",
"age": 36,
"active": true,
"city": "strasbourg",
"address": {
"street": "116 main st",
"zip": "10016",
"custom": {
"info": "custom info 16",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1966-05-17T00:00:00.000Z",
"email": "robert.anderson16@example.com",
"phone": "+33 8 26 26 26 26"
},
{
"name": "merce pite",
"age": 37,
"active": true,
"city": "montpellier",
"address": {
"street": "117 elm st",
"zip": "10017"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1967-06-18T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 38,
"active": false,
"city": "bordeaux",
"address": {
"street": "118 oak ave",
"zip": "10018"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1968-07-19T00:00:00.000Z",
"phone": "+33 1 28 28 28 28"
},
{
"name": "crystal castellucci",
"age": 39,
"active": true,
"city": "lille",
"address": {
"street": "119 maple dr",
"zip": "10019"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1969-08-20T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 40,
"active": true,
"city": "marseille",
"address": {
"street": "120 pine rd",
"zip": "10020",
"custom": {
"info": "custom info 20",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović20@example.com",
"phone": "+33 3 30 30 30 30"
},
{
"name": "pina cunningham",
"age": 41,
"active": false,
"city": "paris",
"address": {
"street": "121 cedar ln",
"zip": "10021",
"custom": {
"info": "custom info 21",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1971-10-22T00:00:00.000Z",
"email": "pina.cunningham21@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 42,
"active": true,
"city": "lyon",
"address": {
"street": "122 birch way",
"zip": "10022"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1972-11-23T00:00:00.000Z",
"email": "laurie.de keersmaeker22@example.com",
"phone": "+33 5 32 32 32 32"
},
{
"name": "romeo bausch",
"age": 43,
"active": true,
"city": "toulouse",
"address": {
"street": "123 ash ct",
"zip": "10023"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1973-12-24T00:00:00.000Z",
"email": "romeo.bausch23@example.com"
},
{
"name": "anne Teresa childs",
"age": 44,
"active": false,
"city": "nice",
"address": {
"street": "124 main st",
"zip": "10024"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1974-01-25T00:00:00.000Z",
"email": "anne Teresa.childs24@example.com",
"phone": "+33 7 34 34 34 34"
},
{
"name": "william forsythe",
"age": 45,
"active": true,
"city": "nantes",
"address": {
"street": "125 elm st",
"zip": "10025",
"custom": {
"info": "custom info 25",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe25@example.com"
},
{
"name": "robert anderson",
"age": 46,
"active": true,
"city": "strasbourg",
"address": {
"street": "126 oak ave",
"zip": "10026",
"custom": {
"info": "custom info 26",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1976-03-27T00:00:00.000Z",
"email": "robert.anderson26@example.com",
"phone": "+33 9 36 36 36 36"
},
{
"name": "merce pite",
"age": 47,
"active": false,
"city": "montpellier",
"address": {
"street": "127 maple dr",
"zip": "10027"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1977-04-28T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 48,
"active": true,
"city": "bordeaux",
"address": {
"street": "128 pine rd",
"zip": "10028"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1978-05-01T00:00:00.000Z",
"phone": "+33 2 38 38 38 38"
},
{
"name": "crystal castellucci",
"age": 49,
"active": true,
"city": "lille",
"address": {
"street": "129 cedar ln",
"zip": "10029"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1979-06-02T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 50,
"active": false,
"city": "marseille",
"address": {
"street": "130 birch way",
"zip": "10030",
"custom": {
"info": "custom info 30",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović30@example.com",
"phone": "+33 4 40 40 40 40"
},
{
"name": "pina cunningham",
"age": 51,
"active": true,
"city": "paris",
"address": {
"street": "131 ash ct",
"zip": "10031",
"custom": {
"info": "custom info 31",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1981-08-04T00:00:00.000Z",
"email": "pina.cunningham31@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 52,
"active": true,
"city": "lyon",
"address": {
"street": "132 main st",
"zip": "10032"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1982-09-05T00:00:00.000Z",
"email": "laurie.de keersmaeker32@example.com",
"phone": "+33 6 42 42 42 42"
},
{
"name": "romeo bausch",
"age": 53,
"active": false,
"city": "toulouse",
"address": {
"street": "133 elm st",
"zip": "10033"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1983-10-06T00:00:00.000Z",
"email": "romeo.bausch33@example.com"
},
{
"name": "anne Teresa childs",
"age": 54,
"active": true,
"city": "nice",
"address": {
"street": "134 oak ave",
"zip": "10034"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1984-11-07T00:00:00.000Z",
"email": "anne Teresa.childs34@example.com",
"phone": "+33 8 44 44 44 44"
},
{
"name": "william forsythe",
"age": 55,
"active": true,
"city": "nantes",
"address": {
"street": "135 maple dr",
"zip": "10035",
"custom": {
"info": "custom info 35",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe35@example.com"
},
{
"name": "robert anderson",
"age": 56,
"active": false,
"city": "strasbourg",
"address": {
"street": "136 pine rd",
"zip": "10036",
"custom": {
"info": "custom info 36",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1986-01-09T00:00:00.000Z",
"email": "robert.anderson36@example.com",
"phone": "+33 1 46 46 46 46"
},
{
"name": "merce pite",
"age": 57,
"active": true,
"city": "montpellier",
"address": {
"street": "137 cedar ln",
"zip": "10037"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1987-02-10T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 58,
"active": true,
"city": "bordeaux",
"address": {
"street": "138 birch way",
"zip": "10038"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1988-03-11T00:00:00.000Z",
"phone": "+33 3 48 48 48 48"
},
{
"name": "crystal castellucci",
"age": 59,
"active": false,
"city": "lille",
"address": {
"street": "139 ash ct",
"zip": "10039"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1989-04-12T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 60,
"active": true,
"city": "marseille",
"address": {
"street": "140 main st",
"zip": "10040",
"custom": {
"info": "custom info 40",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović40@example.com",
"phone": "+33 5 50 50 50 50"
},
{
"name": "pina cunningham",
"age": 61,
"active": true,
"city": "paris",
"address": {
"street": "141 elm st",
"zip": "10041",
"custom": {
"info": "custom info 41",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1991-06-14T00:00:00.000Z",
"email": "pina.cunningham41@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 62,
"active": false,
"city": "lyon",
"address": {
"street": "142 oak ave",
"zip": "10042"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1992-07-15T00:00:00.000Z",
"email": "laurie.de keersmaeker42@example.com",
"phone": "+33 7 52 52 52 52"
},
{
"name": "romeo bausch",
"age": 63,
"active": true,
"city": "toulouse",
"address": {
"street": "143 maple dr",
"zip": "10043"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1993-08-16T00:00:00.000Z",
"email": "romeo.bausch43@example.com"
},
{
"name": "anne Teresa childs",
"age": 64,
"active": true,
"city": "nice",
"address": {
"street": "144 pine rd",
"zip": "10044"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1994-09-17T00:00:00.000Z",
"email": "anne Teresa.childs44@example.com",
"phone": "+33 9 54 54 54 54"
},
{
"name": "william forsythe",
"age": 65,
"active": false,
"city": "nantes",
"address": {
"street": "145 cedar ln",
"zip": "10045",
"custom": {
"info": "custom info 45",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe45@example.com"
},
{
"name": "robert anderson",
"age": 66,
"active": true,
"city": "strasbourg",
"address": {
"street": "146 birch way",
"zip": "10046",
"custom": {
"info": "custom info 46",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1996-11-19T00:00:00.000Z",
"email": "robert.anderson46@example.com",
"phone": "+33 2 56 56 56 56"
},
{
"name": "merce pite",
"age": 67,
"active": true,
"city": "montpellier",
"address": {
"street": "147 ash ct",
"zip": "10047"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1997-12-20T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 68,
"active": false,
"city": "bordeaux",
"address": {
"street": "148 main st",
"zip": "10048"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1998-01-21T00:00:00.000Z",
"phone": "+33 4 58 58 58 58"
},
{
"name": "crystal castellucci",
"age": 69,
"active": true,
"city": "lille",
"address": {
"street": "149 elm st",
"zip": "10049"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1999-02-22T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 20,
"active": true,
"city": "marseille",
"address": {
"street": "150 oak ave",
"zip": "10050",
"custom": {
"info": "custom info 50",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović50@example.com",
"phone": "+33 6 60 60 60 60"
},
{
"name": "pina cunningham",
"age": 21,
"active": false,
"city": "paris",
"address": {
"street": "151 maple dr",
"zip": "10051",
"custom": {
"info": "custom info 51",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "2001-04-24T00:00:00.000Z",
"email": "pina.cunningham51@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 22,
"active": true,
"city": "lyon",
"address": {
"street": "152 pine rd",
"zip": "10052"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "2002-05-25T00:00:00.000Z",
"email": "laurie.de keersmaeker52@example.com",
"phone": "+33 8 62 62 62 62"
},
{
"name": "romeo bausch",
"age": 23,
"active": true,
"city": "toulouse",
"address": {
"street": "153 cedar ln",
"zip": "10053"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "2003-06-26T00:00:00.000Z",
"email": "romeo.bausch53@example.com"
},
{
"name": "anne Teresa childs",
"age": 24,
"active": false,
"city": "nice",
"address": {
"street": "154 birch way",
"zip": "10054"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "2004-07-27T00:00:00.000Z",
"email": "anne Teresa.childs54@example.com",
"phone": "+33 1 64 64 64 64"
},
{
"name": "william forsythe",
"age": 25,
"active": true,
"city": "nantes",
"address": {
"street": "155 ash ct",
"zip": "10055",
"custom": {
"info": "custom info 55",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe55@example.com"
},
{
"name": "robert anderson",
"age": 26,
"active": true,
"city": "strasbourg",
"address": {
"street": "156 main st",
"zip": "10056",
"custom": {
"info": "custom info 56",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1951-09-01T00:00:00.000Z",
"email": "robert.anderson56@example.com",
"phone": "+33 3 66 66 66 66"
},
{
"name": "merce pite",
"age": 27,
"active": false,
"city": "montpellier",
"address": {
"street": "157 elm st",
"zip": "10057"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1952-10-02T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 28,
"active": true,
"city": "bordeaux",
"address": {
"street": "158 oak ave",
"zip": "10058"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1953-11-03T00:00:00.000Z",
"phone": "+33 5 68 68 68 68"
},
{
"name": "crystal castellucci",
"age": 29,
"active": true,
"city": "lille",
"address": {
"street": "159 maple dr",
"zip": "10059"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1954-12-04T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 30,
"active": false,
"city": "marseille",
"address": {
"street": "160 pine rd",
"zip": "10060",
"custom": {
"info": "custom info 60",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović60@example.com",
"phone": "+33 7 70 70 70 70"
},
{
"name": "pina cunningham",
"age": 31,
"active": true,
"city": "paris",
"address": {
"street": "161 cedar ln",
"zip": "10061",
"custom": {
"info": "custom info 61",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1956-02-06T00:00:00.000Z",
"email": "pina.cunningham61@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 32,
"active": true,
"city": "lyon",
"address": {
"street": "162 birch way",
"zip": "10062"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1957-03-07T00:00:00.000Z",
"email": "laurie.de keersmaeker62@example.com",
"phone": "+33 9 72 72 72 72"
},
{
"name": "romeo bausch",
"age": 33,
"active": false,
"city": "toulouse",
"address": {
"street": "163 ash ct",
"zip": "10063"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1958-04-08T00:00:00.000Z",
"email": "romeo.bausch63@example.com"
},
{
"name": "anne Teresa childs",
"age": 34,
"active": true,
"city": "nice",
"address": {
"street": "164 main st",
"zip": "10064"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1959-05-09T00:00:00.000Z",
"email": "anne Teresa.childs64@example.com",
"phone": "+33 2 74 74 74 74"
},
{
"name": "william forsythe",
"age": 35,
"active": true,
"city": "nantes",
"address": {
"street": "165 elm st",
"zip": "10065",
"custom": {
"info": "custom info 65",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe65@example.com"
},
{
"name": "robert anderson",
"age": 36,
"active": false,
"city": "strasbourg",
"address": {
"street": "166 oak ave",
"zip": "10066",
"custom": {
"info": "custom info 66",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1961-07-11T00:00:00.000Z",
"email": "robert.anderson66@example.com",
"phone": "+33 4 76 76 76 76"
},
{
"name": "merce pite",
"age": 37,
"active": true,
"city": "montpellier",
"address": {
"street": "167 maple dr",
"zip": "10067"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1962-08-12T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 38,
"active": true,
"city": "bordeaux",
"address": {
"street": "168 pine rd",
"zip": "10068"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1963-09-13T00:00:00.000Z",
"phone": "+33 6 78 78 78 78"
},
{
"name": "crystal castellucci",
"age": 39,
"active": false,
"city": "lille",
"address": {
"street": "169 cedar ln",
"zip": "10069"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1964-10-14T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 40,
"active": true,
"city": "marseille",
"address": {
"street": "170 birch way",
"zip": "10070",
"custom": {
"info": "custom info 70",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović70@example.com",
"phone": "+33 8 80 80 80 80"
},
{
"name": "pina cunningham",
"age": 41,
"active": true,
"city": "paris",
"address": {
"street": "171 ash ct",
"zip": "10071",
"custom": {
"info": "custom info 71",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1966-12-16T00:00:00.000Z",
"email": "pina.cunningham71@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 42,
"active": false,
"city": "lyon",
"address": {
"street": "172 main st",
"zip": "10072"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1967-01-17T00:00:00.000Z",
"email": "laurie.de keersmaeker72@example.com",
"phone": "+33 1 82 82 82 82"
},
{
"name": "romeo bausch",
"age": 43,
"active": true,
"city": "toulouse",
"address": {
"street": "173 elm st",
"zip": "10073"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1968-02-18T00:00:00.000Z",
"email": "romeo.bausch73@example.com"
},
{
"name": "anne Teresa childs",
"age": 44,
"active": true,
"city": "nice",
"address": {
"street": "174 oak ave",
"zip": "10074"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1969-03-19T00:00:00.000Z",
"email": "anne Teresa.childs74@example.com",
"phone": "+33 3 84 84 84 84"
},
{
"name": "william forsythe",
"age": 45,
"active": false,
"city": "nantes",
"address": {
"street": "175 maple dr",
"zip": "10075",
"custom": {
"info": "custom info 75",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe75@example.com"
},
{
"name": "robert anderson",
"age": 46,
"active": true,
"city": "strasbourg",
"address": {
"street": "176 pine rd",
"zip": "10076",
"custom": {
"info": "custom info 76",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1971-05-21T00:00:00.000Z",
"email": "robert.anderson76@example.com",
"phone": "+33 5 86 86 86 86"
},
{
"name": "merce pite",
"age": 47,
"active": true,
"city": "montpellier",
"address": {
"street": "177 cedar ln",
"zip": "10077"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1972-06-22T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 48,
"active": false,
"city": "bordeaux",
"address": {
"street": "178 birch way",
"zip": "10078"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1973-07-23T00:00:00.000Z",
"phone": "+33 7 88 88 88 88"
},
{
"name": "crystal castellucci",
"age": 49,
"active": true,
"city": "lille",
"address": {
"street": "179 ash ct",
"zip": "10079"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1974-08-24T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 50,
"active": true,
"city": "marseille",
"address": {
"street": "180 main st",
"zip": "10080",
"custom": {
"info": "custom info 80",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović80@example.com",
"phone": "+33 9 90 90 90 90"
},
{
"name": "pina cunningham",
"age": 51,
"active": false,
"city": "paris",
"address": {
"street": "181 elm st",
"zip": "10081",
"custom": {
"info": "custom info 81",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1976-10-26T00:00:00.000Z",
"email": "pina.cunningham81@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 52,
"active": true,
"city": "lyon",
"address": {
"street": "182 oak ave",
"zip": "10082"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1977-11-27T00:00:00.000Z",
"email": "laurie.de keersmaeker82@example.com",
"phone": "+33 2 92 92 92 92"
},
{
"name": "romeo bausch",
"age": 53,
"active": true,
"city": "toulouse",
"address": {
"street": "183 maple dr",
"zip": "10083"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1978-12-28T00:00:00.000Z",
"email": "romeo.bausch83@example.com"
},
{
"name": "anne Teresa childs",
"age": 54,
"active": false,
"city": "nice",
"address": {
"street": "184 pine rd",
"zip": "10084"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1979-01-01T00:00:00.000Z",
"email": "anne Teresa.childs84@example.com",
"phone": "+33 4 94 94 94 94"
},
{
"name": "william forsythe",
"age": 55,
"active": true,
"city": "nantes",
"address": {
"street": "185 cedar ln",
"zip": "10085",
"custom": {
"info": "custom info 85",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe85@example.com"
},
{
"name": "robert anderson",
"age": 56,
"active": true,
"city": "strasbourg",
"address": {
"street": "186 birch way",
"zip": "10086",
"custom": {
"info": "custom info 86",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1981-03-03T00:00:00.000Z",
"email": "robert.anderson86@example.com",
"phone": "+33 6 96 96 96 96"
},
{
"name": "merce pite",
"age": 57,
"active": false,
"city": "montpellier",
"address": {
"street": "187 ash ct",
"zip": "10087"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1982-04-04T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 58,
"active": true,
"city": "bordeaux",
"address": {
"street": "188 main st",
"zip": "10088"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1983-05-05T00:00:00.000Z",
"phone": "+33 8 98 98 98 98"
},
{
"name": "crystal castellucci",
"age": 59,
"active": true,
"city": "lille",
"address": {
"street": "189 elm st",
"zip": "10089"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1984-06-06T00:00:00.000Z"
},
{
"name": "marina abramović",
"age": 60,
"active": false,
"city": "marseille",
"address": {
"street": "190 oak ave",
"zip": "10090",
"custom": {
"info": "custom info 90",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "marina.abramović90@example.com",
"phone": "+33 1 10 10 10 10"
},
{
"name": "pina cunningham",
"age": 61,
"active": true,
"city": "paris",
"address": {
"street": "191 maple dr",
"zip": "10091",
"custom": {
"info": "custom info 91",
"tags": [
"avant-garde",
"experimental"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1986-08-08T00:00:00.000Z",
"email": "pina.cunningham91@example.com"
},
{
"name": "laurie de keersmaeker",
"age": 62,
"active": true,
"city": "lyon",
"address": {
"street": "192 pine rd",
"zip": "10092"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1987-09-09T00:00:00.000Z",
"email": "laurie.de keersmaeker92@example.com",
"phone": "+33 3 12 12 12 12"
},
{
"name": "romeo bausch",
"age": 63,
"active": false,
"city": "toulouse",
"address": {
"street": "193 cedar ln",
"zip": "10093"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1988-10-10T00:00:00.000Z",
"email": "romeo.bausch93@example.com"
},
{
"name": "anne Teresa childs",
"age": 64,
"active": true,
"city": "nice",
"address": {
"street": "194 birch way",
"zip": "10094"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1989-11-11T00:00:00.000Z",
"email": "anne Teresa.childs94@example.com",
"phone": "+33 5 14 14 14 14"
},
{
"name": "william forsythe",
"age": 65,
"active": true,
"city": "nantes",
"address": {
"street": "195 ash ct",
"zip": "10095",
"custom": {
"info": "custom info 95",
"tags": [
"avant-garde",
"experimental",
"contemporary"
]
}
},
"hobbies": [
"performance art",
"installation",
"video art"
],
"email": "william.forsythe95@example.com"
},
{
"name": "robert anderson",
"age": 66,
"active": false,
"city": "strasbourg",
"address": {
"street": "196 main st",
"zip": "10096",
"custom": {
"info": "custom info 96",
"tags": [
"avant-garde"
]
}
},
"hobbies": [
"choreography",
"contemporary dance",
"butoh"
],
"dob": "1991-01-13T00:00:00.000Z",
"email": "robert.anderson96@example.com",
"phone": "+33 7 16 16 16 16"
},
{
"name": "merce pite",
"age": 67,
"active": true,
"city": "montpellier",
"address": {
"street": "197 elm st",
"zip": "10097"
},
"hobbies": [
"experimental music",
"multimedia",
"storytelling"
],
"dob": "1992-02-14T00:00:00.000Z"
},
{
"name": "lucinda wilson",
"age": 68,
"active": true,
"city": "bordeaux",
"address": {
"street": "198 oak ave",
"zip": "10098"
},
"hobbies": [
"theatre direction",
"scenography",
"dramaturgy"
],
"dob": "1993-03-15T00:00:00.000Z",
"phone": "+33 9 18 18 18 18"
},
{
"name": "crystal castellucci",
"age": 69,
"active": false,
"city": "lille",
"address": {
"street": "199 maple dr",
"zip": "10099"
},
"hobbies": [
"physical theatre",
"improvisation",
"composition"
],
"dob": "1994-04-16T00:00:00.000Z"
}
]This example showcases VueAirport's component-based pattern where:
useCheckInobject-transformer/
├── index.ts # Shared types and desk key
├── ExampleTransformer.vue # Demo wrapper (creates desk)
├── ModeToggle.vue # Object/Model mode switch
├── NodeActions.vue # Transform/delete actions
├── NodeKeyEditor.vue # Inline key editing
├── NodeOpen.vue # Expand/collapse toggle
├── ObjectNode.vue # Recursive tree node
├── ObjectPreview.vue # JSON preview display
├── ObjectTransformer.vue # Root container component
├── RecipePreview.vue # Recipe JSON preview
├── TransformParam.vue # Transform parameters editor
├── TransformSelect.vue # Transform selector dropdown
├── transforms/ # Transform category components
│ ├── TransformArray.vue # Array transforms (Map, Filter, etc.)
│ ├── TransformBoolean.vue # Boolean transforms
│ ├── TransformDate.vue # Date transforms (Format, ISO, etc.)
│ ├── TransformNumber.vue # Number transforms (Round, Abs, etc.)
│ ├── TransformObject.vue # Object transforms (Merge, Flatten, etc.)
│ └── TransformString.vue # String transforms (Split, Uppercase, etc.)
└── utils/
├── common-structural-handlers.util.ts # Common structural transform handlers
├── functional.util.ts # Functional utilities (partition, etc.)
├── model-mode.util.ts # Model mode helpers
├── model-rules.util.ts # Model transformation rules
├── node-builder.util.ts # Tree node construction
├── node-editing.util.ts # Node editing operations
├── node-transforms.util.ts # Node transform application
├── node-utilities.util.ts # Node utility functions
├── structural-transform-handlers.util.ts # Structural transform handlers
├── transform-propagation.util.ts # Structural transform propagation
├── transform-recipe.util.ts # Recipe serialization/application
└── type-guards.util.ts # Type guard utilities
Creates the desk and provides initial data. No props are passed to children except an id - they all register independently:
<script setup lang="ts">
import {
ObjectTransformer,
ObjectPreview,
RecipePreview,
ObjectNode,
ModeToggle,
TransformString,
TransformNumber,
TransformDate,
TransformBoolean,
TransformObject,
TransformArray,
} from '.';
// Array of user objects for model mode demonstration
const data = [
{
name: 'john doe',
age: 30,
dob: new Date('1993-05-15T00:00:00Z'),
active: true,
city: 'marseille',
address: {
street: '123 main st',
zip: '13001',
custom: {
info: 'some custom info',
tags: ['tag1', 'tag2'],
},
},
hobbies: ['reading', 'traveling', 'swimming'],
},
{
name: 'jane smith',
age: 28,
active: false,
city: 'paris',
address: {
street: '456 elm st',
zip: '75001',
},
hobbies: ['cooking', 'painting'],
},
{
name: 'bob wilson',
age: 35,
dob: new Date('1988-03-20T00:00:00Z'),
active: true,
city: 'lyon',
address: {
street: '789 oak ave',
zip: '69001',
custom: {
info: 'another info',
},
},
},
];
</script>
<template>
<div class="space-y-4 max-h-196 overflow-auto">
<!-- ObjectTransformer creates the desk internally -->
<ObjectTransformer :data="data" class="flex md:flex-row w-full">
<!-- Transform category components - register independently -->
<TransformString />
<TransformNumber />
<TransformDate />
<TransformBoolean />
<TransformObject />
<TransformArray />
<!-- Tree editor - registers independently -->
<div class="flex-1 flex flex-col gap-2">
<ModeToggle />
<ObjectNode />
</div>
<!-- Preview panels - register independently -->
<div class="flex-1 flex flex-col gap-2 h-full">
<ObjectPreview />
<RecipePreview />
</div>
</ObjectTransformer>
</div>
</template>
Notice: No props drilling! Each component (TransformString, ObjectNode, ObjectPreview, etc.) accesses the desk independently through useCheckIn.
Transform components register transform definitions with the desk on mount. Each transform category is a Vue component:
<script setup lang="ts">
import { useCheckIn } from 'vue-airport';
import type { ObjectTransformerContext, Transform } from '..';
import { ObjectTransformerDeskKey, registerStructuralTransformHandler } from '..';
type DeskWithContext = typeof desk & ObjectTransformerContext;
// Register structural transform handler for 'split'
registerStructuralTransformHandler('split', (current, lastKey, result) => {
if (!Array.isArray(result.parts)) return;
// Create new properties from parts
result.parts.forEach((part: any, index: number) => {
const newKey = `${lastKey}_${index}`;
current[newKey] = part;
});
// Remove source if specified
if (result.removeSource) {
delete current[lastKey];
}
});
const transforms: Transform[] = [
{
name: 'Split',
structural: true, // Structural transform creates new nodes
if: (node) => node.type === 'string',
params: [{ key: 'delimiter', label: 'Delimiter', type: 'text', default: ' ' }],
fn: (v: string, delimiter: string) => {
if (typeof v !== 'string') return v;
return {
__structuralChange: true,
action: 'split' as const,
parts: v.split(delimiter),
removeSource: false,
};
},
},
{
name: 'Uppercase',
if: (node) => node.type === 'string',
fn: (v: any) => (typeof v === 'string' ? v.toUpperCase() : v),
},
{
name: 'Capitalized',
if: (node) => node.type === 'string',
fn: (v: any) =>
typeof v === 'string' ? v.charAt(0).toUpperCase() + v.slice(1).toLowerCase() : v,
},
{
name: 'To Object',
structural: true,
if: (node) => node.type === 'string',
fn: (v: string) => {
if (typeof v !== 'string') return v;
return {
__structuralChange: true,
action: 'toObject' as const,
object: { object: { value: v } },
removeSource: false,
};
},
},
// ... 10+ more string transforms
];
// Register with desk on mount - no props needed!
const { checkIn } = useCheckIn<Transform, ObjectTransformerContext>();
const { desk } = checkIn(ObjectTransformerDeskKey, {
id: 'string-transform',
autoCheckIn: true,
});
onMounted(() => {
const d = desk as DeskWithContext;
d.addTransforms(...transforms); // Register transforms with shared desk
});
</script>
<template>
<!-- No UI - just registers transforms on mount -->
<div class="hidden"></div>
</template>
Key Points:
desk.addTransforms()TransformSelect) access these transforms from desk contextObjectTransformer creates a desk with shared context:
// ObjectTransformer.vue (simplified)
const { createDesk } = useCheckIn<ObjectNodeData, TransformerContext>();
const { desk } = createDesk(OBJECT_TRANSFORMER_DESK_KEY, {
devTools: true,
context: {
tree: ref<ObjectNodeData[]>([]),
originalData: ref(props.data),
mode: ref<'object' | 'model'>('object'),
transforms: ALL_TRANSFORMS,
// ... other shared state
},
});
Child components register without any props:
// ObjectNode.vue, ObjectPreview.vue, TransformString.vue, etc.
const { checkIn } = useCheckIn<ObjectNodeData, TransformerContext>();
const { desk } = checkIn(OBJECT_TRANSFORMER_DESK_KEY, {
autoCheckIn: false,
watchData: false,
});
// Access shared state directly
const tree = computed(() => desk!.tree);
const mode = computed(() => desk!.mode.value);
const transforms = computed(() => desk!.transforms);
This pattern eliminates props drilling and enables flexible component composition.
Each node maintains three distinct keys for robust rename tracking:
firstKey: Immutable original key at creation (never changes)originalKey: Current expected key reflecting parent structural changeskey: Actual display key (custom if manually renamed via keyModified flag)This system ensures:
Example flow:
// Initial state
{ firstKey: 'name', originalKey: 'name', key: 'name', keyModified: false }
// User renames to 'fullName'
{ firstKey: 'name', originalKey: 'name', key: 'fullName', keyModified: true }
// Parent applies 'Split' transform creating 'name_object'
// Child's originalKey updates, but user rename preserved
{ firstKey: 'name', originalKey: 'name_object', key: 'fullName', keyModified: true }
Transforms are categorized by structural impact:
Structural Transforms (create/remove nodes):
To Object, Split, Array to PropertiesoriginalKey for affected childrenkeyModified flagNon-Structural Transforms (modify values):
Capitalized, Uppercase, Lowercase, Trim, Number, etc.transform propertyRecipes are portable JSON documents describing transformations:
interface TransformRecipe {
steps: Array<{
path: string[]; // Path to target node (for transforms/deletions)
renamePath: string[]; // Path for renames (reflects current structure)
transform?: string; // Transform name
params?: any; // Transform parameters
}>;
deletions: string[][]; // Paths to deleted nodes
renames: Array<{
path: string[]; // Path to renamed node
newKey: string; // New key name
}>;
}
Recipe Generation (buildRecipe):
originalPath for data operations (transforms/deletions)renamePath for rename operations (current structure)Recipe Application (applyRecipe):
Object Mode: Edit single object directly
Model Mode:
Nodes created by structural transforms maintain identity:
splitSourceId: ID of source node that created this nodesplitIndex: Position in split (0, 1, 2...)This enables node reuse when structural transforms re-execute, preserving user customizations.
buildNodeTree creates recursive structure from datakey and sets keyModified: truetransform property, triggers propagation if structuralisDeleted: truesplitSourceId and splitIndexoriginalKey for children affected by parent changeskey if keyModified: trueoriginalDatabuildRecipe traverses tree:
originalPath (data reference)originalPathrenamePath (current structure)applyRecipe detects data type:
applySingleRecipe executes sequentially:
When importing an object recipe to array data:
// Recipe for single object
const recipe = {
steps: [
{ path: ['name'], renamePath: ['name'], transform: 'Capitalized' }
],
renames: [
{ path: ['name'], newKey: 'fullName' }
]
};
// Applied to array
const arrayData = [
{ name: 'alice' },
{ name: 'bob' }
];
// Result: recipe applied to each element
const result = [
{ fullName: 'Alice' },
{ fullName: 'Bob' }
];
Case Transforms: Capitalized, Uppercase, Lowercase, Title Case, Camel Case, Snake Case, Kebab Case
Type Conversions: Number, String, Boolean, Parse JSON, Stringify JSON
String Manipulation: Trim, Trim Start, Trim End, Reverse, Length, Truncate, Pad Start, Pad End
Structural: To Object, Split, Array to Properties, Flatten, Merge
Numeric: Absolute, Round, Floor, Ceil, Increment, Decrement
Date/Time: Format Date, ISO String, Timestamp
Data Operations: Remove Nulls, Remove Empty Strings, Deduplicate, Sort
This pattern is ideal for:
Traditional approach (props drilling):
<!-- ❌ Props drilling - brittle and verbose -->
<ObjectTransformer :data="data">
<ObjectNode :tree="tree" :transforms="transforms" :mode="mode">
<NodeActions :tree="tree" :transforms="transforms" />
<NodeKeyEditor :node="node" :tree="tree" @update="handleUpdate" />
</ObjectNode>
<ObjectPreview :tree="tree" :original="data" />
</ObjectTransformer>
VueAirport approach (desk registration):
<!-- ✅ No props - components register independently -->
<ObjectTransformer :data="data">
<ObjectNode />
<ObjectPreview />
<TransformString />
<RecipePreview />
</ObjectTransformer>
Benefits:
The combination of visual editing, portable recipes, template mode, and component-based architecture makes it a powerful tool for complex data transformations.