@builder.io/mitosis 0.9.3 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,334 +1,287 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.componentToSwift = void 0;
7
- const event_handlers_1 = require("../../helpers/event-handlers");
8
- const legacy_1 = __importDefault(require("neotraverse/legacy"));
9
4
  const dedent_1 = require("../../helpers/dedent");
10
5
  const fast_clone_1 = require("../../helpers/fast-clone");
11
- const filter_empty_text_nodes_1 = require("../../helpers/filter-empty-text-nodes");
12
6
  const generic_format_1 = require("../../helpers/generic-format");
13
- const get_state_object_string_1 = require("../../helpers/get-state-object-string");
14
- const get_styles_1 = require("../../helpers/get-styles");
15
- const is_children_1 = __importDefault(require("../../helpers/is-children"));
16
- const is_mitosis_node_1 = require("../../helpers/is-mitosis-node");
17
- const state_1 = require("../../helpers/state");
18
- const try_prettier_format_1 = require("../../helpers/try-prettier-format");
19
- const mitosis_node_1 = require("../../types/mitosis-node");
20
- const scrolls = (json) => {
21
- var _a;
22
- return ((_a = (0, get_styles_1.getStyles)(json)) === null || _a === void 0 ? void 0 : _a.overflow) === 'auto';
23
- };
24
- const mappers = {
25
- Fragment: (json, options) => {
26
- return `${json.children.map((item) => blockToSwift(item, options)).join('\n')}`;
27
- },
28
- link: () => '',
29
- Image: (json, options) => {
30
- var _a;
31
- return (`Image(${processBinding((_a = json.bindings.image) === null || _a === void 0 ? void 0 : _a.code, options) || `"${json.properties.image}"`})` +
32
- getStyleString(json, options) +
33
- getActionsString(json, options));
34
- },
35
- input: (json, options) => {
36
- var _a, _b;
37
- const name = json.properties.$name;
38
- let str = `TextField(${json.bindings.placeholder
39
- ? processBinding((_a = json.bindings.placeholder) === null || _a === void 0 ? void 0 : _a.code, options)
40
- : json.properties.placeholder
41
- ? JSON.stringify(json.bindings.placeholder.code)
42
- : '""'}, text: $${name})` +
43
- getStyleString(json, options) +
44
- getActionsString(json, options);
45
- if (json.bindings.onChange) {
46
- str += `
47
- .onChange(of: ${name}) { ${name} in
48
- ${processBinding(wrapAction(`var event = { target: { value: "\\(${name})" } };
49
- ${(_b = json.bindings.onChange) === null || _b === void 0 ? void 0 : _b.code}`), options)}
50
- }`;
51
- }
52
- return str;
53
- },
7
+ const get_props_1 = require("../../helpers/get-props");
8
+ const get_refs_1 = require("../../helpers/get-refs");
9
+ const getters_to_functions_1 = require("../../helpers/getters-to-functions");
10
+ const merge_options_1 = require("../../helpers/merge-options");
11
+ const on_event_1 = require("../../helpers/on-event");
12
+ const patterns_1 = require("../../helpers/patterns");
13
+ const process_code_1 = require("../../helpers/plugins/process-code");
14
+ const slots_1 = require("../../helpers/slots");
15
+ const strip_meta_properties_1 = require("../../helpers/strip-meta-properties");
16
+ const plugins_1 = require("../../modules/plugins");
17
+ const blocks_1 = require("./blocks");
18
+ const helpers_1 = require("./helpers");
19
+ const DEFAULT_OPTIONS = {
20
+ stateType: 'state',
21
+ formatCode: true,
22
+ includeTypes: true,
23
+ includePreview: true,
24
+ classPrefix: '',
54
25
  };
55
- const blockToSwift = (json, options) => {
26
+ const componentToSwift = (userProvidedOptions) => ({ component }) => {
56
27
  var _a, _b;
57
- if (mappers[json.name]) {
58
- return mappers[json.name](json, options);
59
- }
60
- // TODO: Add support for `{props.children}` bindings
61
- // Right now we return an empty string because the generated code
62
- // is very likely wrong.
63
- if ((0, is_children_1.default)({ node: json })) {
64
- return '/* `props.children` is not supported yet for SwiftUI */';
65
- }
66
- if (json.properties._text) {
67
- if (!json.properties._text.trim().length) {
68
- return '';
69
- }
70
- return `Text("${json.properties._text.trim().replace(/\s+/g, ' ')}")`;
71
- }
72
- if (json.bindings._text) {
73
- return `Text(${processBinding(json.bindings._text.code, options)}.toString())`;
74
- }
75
- let str = '';
76
- const children = json.children.filter(filter_empty_text_nodes_1.filterEmptyTextNodes);
77
- const style = (0, get_styles_1.getStyles)(json);
78
- // TODO: do as preprocess step and do more mappings of dom attributes to special
79
- // Image, TextField, etc component props
80
- const name = json.name === 'input'
81
- ? 'TextField'
82
- : json.name === 'img'
83
- ? 'Image'
84
- : json.name[0].toLowerCase() === json.name[0]
85
- ? scrolls(json)
86
- ? 'ScrollView'
87
- : (style === null || style === void 0 ? void 0 : style.display) === 'flex' && style.flexDirection !== 'column'
88
- ? 'HStack'
89
- : 'VStack'
90
- : json.name;
91
- if (name === 'TextField') {
92
- const placeholder = json.properties.placeholder;
93
- delete json.properties.placeholder;
94
- json.properties._ = placeholder || '';
95
- }
96
- if ((0, mitosis_node_1.checkIsForNode)(json)) {
97
- str += `ForEach(${processBinding((_a = json.bindings.each) === null || _a === void 0 ? void 0 : _a.code, options)}, id: \\.self) { ${json.scope.forName} in ${children
98
- .map((item) => blockToSwift(item, options))
99
- .join('\n')} }`;
100
- }
101
- else if (json.name === 'Show') {
102
- str += `if ${processBinding((_b = json.bindings.when) === null || _b === void 0 ? void 0 : _b.code, options)} {
103
- ${children.map((item) => blockToSwift(item, options)).join('\n')}
104
- }`;
105
- }
106
- else {
107
- str += `${name}(`;
108
- for (const key in json.properties) {
109
- if (key === 'class' || key === 'className') {
110
- continue;
28
+ const options = (0, merge_options_1.initializeOptions)({
29
+ target: 'swift',
30
+ component,
31
+ defaults: DEFAULT_OPTIONS,
32
+ userOptions: userProvidedOptions,
33
+ });
34
+ options.plugins = [
35
+ ...(options.plugins || []),
36
+ (0, on_event_1.processOnEventHooksPlugin)(),
37
+ (0, process_code_1.CODE_PROCESSOR_PLUGIN)((codeType) => {
38
+ switch (codeType) {
39
+ case 'bindings':
40
+ case 'properties':
41
+ case 'hooks':
42
+ case 'hooks-deps':
43
+ case 'hooks-deps-array':
44
+ case 'state':
45
+ case 'context-set':
46
+ case 'dynamic-jsx-elements':
47
+ case 'types':
48
+ return (x) => (0, helpers_1.convertConsoleLogToPrint)(x);
49
+ }
50
+ }),
51
+ (0, process_code_1.CODE_PROCESSOR_PLUGIN)((codeType) => {
52
+ switch (codeType) {
53
+ case 'hooks':
54
+ return (code) => (0, helpers_1.stripStateAndProps)({ json, options })(code);
55
+ case 'bindings':
56
+ case 'hooks-deps':
57
+ case 'state':
58
+ return (code) => (0, patterns_1.stripGetter)((0, helpers_1.stripStateAndProps)({ json, options })(code));
59
+ case 'properties':
60
+ case 'context-set':
61
+ return (code) => (0, helpers_1.stripStateAndProps)({ json, options })(code);
62
+ case 'dynamic-jsx-elements':
63
+ case 'hooks-deps-array':
64
+ case 'types':
65
+ return (x) => (0, helpers_1.convertConsoleLogToPrint)(x);
111
66
  }
112
- // TODO: binding mappings
113
- // const value = json.properties[key];
114
- // str += ` ${key}: "${(value as string).replace(/"/g, '"')}", `;
115
- console.warn(`Unsupported property "${key}"`);
67
+ }),
68
+ ];
69
+ // Make a copy we can safely mutate
70
+ let json = (0, fast_clone_1.fastClone)(component);
71
+ json = (0, plugins_1.runPreJsonPlugins)({ json, plugins: options.plugins });
72
+ (0, getters_to_functions_1.gettersToFunctions)(json);
73
+ const componentName = options.classPrefix + (json.name || ((_a = json.meta.useMetadata) === null || _a === void 0 ? void 0 : _a.name) || 'MitosisComponent');
74
+ // Process props
75
+ const filteredProps = Array.from((0, get_props_1.getProps)(json)).filter((prop) => !(0, slots_1.isSlotProperty)(prop));
76
+ const props = Array.from(new Set(filteredProps));
77
+ // Process refs (not directly applicable in SwiftUI, will be converted to @State)
78
+ const refs = Array.from((0, get_refs_1.getRefs)(json))
79
+ .map((0, helpers_1.stripStateAndProps)({ json, options }))
80
+ .filter((x) => !props.includes(x));
81
+ json = (0, plugins_1.runPostJsonPlugins)({ json, plugins: options.plugins });
82
+ (0, strip_meta_properties_1.stripMetaProperties)(json);
83
+ // Generate state variables
84
+ const stateProperties = Object.entries(json.state)
85
+ .filter(([_, value]) => {
86
+ // Skip methods - they'll be handled separately
87
+ return !((value === null || value === void 0 ? void 0 : value.type) === 'method' ||
88
+ ((value === null || value === void 0 ? void 0 : value.code) && (value.code.includes('function') || value.code.includes('=>'))));
89
+ })
90
+ .map(([key, value]) => {
91
+ var _a, _b, _c, _d, _e;
92
+ // Check for value properties safely
93
+ const propertyType = value === null || value === void 0 ? void 0 : value.propertyType;
94
+ // Determine Swift type - handle missing type property
95
+ let valueType = 'Any';
96
+ if (value === null || value === void 0 ? void 0 : value.typeParameter) {
97
+ valueType = value.typeParameter;
116
98
  }
117
- for (const key in json.bindings) {
118
- if (
119
- // TODO: implement spread, ref, more css
120
- key === '_spread' ||
121
- key === 'ref' ||
122
- key === 'css' ||
123
- key === 'class' ||
124
- key === 'className') {
125
- continue;
99
+ else {
100
+ // Try to infer type from code if possible
101
+ if (((_a = value === null || value === void 0 ? void 0 : value.code) === null || _a === void 0 ? void 0 : _a.includes('"')) || ((_b = value === null || value === void 0 ? void 0 : value.code) === null || _b === void 0 ? void 0 : _b.includes("'"))) {
102
+ valueType = 'string';
103
+ }
104
+ else if ((_c = value === null || value === void 0 ? void 0 : value.code) === null || _c === void 0 ? void 0 : _c.match(/^[0-9]+(\.[0-9]+)?$/)) {
105
+ valueType = 'number';
126
106
  }
127
- if ((0, event_handlers_1.checkIsEvent)(key)) {
128
- if (key === 'onClick') {
129
- continue;
130
- }
131
- else {
132
- // TODO: other event mappings
133
- console.warn(`Unsupported event binding "${key}"`);
134
- }
107
+ else if ((value === null || value === void 0 ? void 0 : value.code) === 'true' || (value === null || value === void 0 ? void 0 : value.code) === 'false') {
108
+ valueType = 'boolean';
135
109
  }
136
- else {
137
- console.warn(`Unsupported binding "${key}"`);
138
- // TODO: need binding mappings
139
- // str += ` ${key}: ${processBinding(value, options)}, `;
110
+ else if (((_d = value === null || value === void 0 ? void 0 : value.code) === null || _d === void 0 ? void 0 : _d.startsWith('[')) || ((_e = value === null || value === void 0 ? void 0 : value.code) === null || _e === void 0 ? void 0 : _e.startsWith('Array'))) {
111
+ valueType = 'Array<Any>';
140
112
  }
141
113
  }
142
- str += `)`;
143
- str += ` {`;
144
- if (json.children) {
145
- str += json.children.map((item) => blockToSwift(item, options)).join('\n');
114
+ const typeAnnotation = (0, helpers_1.getStatePropertyTypeAnnotation)(propertyType, valueType);
115
+ const swiftType = (0, helpers_1.getSwiftType)(valueType);
116
+ let stateDeclaration = `${typeAnnotation} ${key}: ${swiftType}`;
117
+ // Add default value if present
118
+ if (value === null || value === void 0 ? void 0 : value.code) {
119
+ stateDeclaration += ` = ${value.code}`;
146
120
  }
147
- str += `}`;
148
- str += getStyleString(json, options);
149
- str += getActionsString(json, options);
150
- }
151
- return str;
152
- };
153
- const wrapAction = (str) => `(() => { ${str} })()`;
154
- function getActionsString(json, options) {
155
- let str = '';
156
- if (json.bindings.onClick) {
157
- str += `\n.onTapGesture {
158
- ${processBinding(wrapAction(json.bindings.onClick.code), options)}
159
- }`;
160
- }
161
- return str;
162
- }
163
- function getStyleString(node, options) {
164
- const style = (0, get_styles_1.getStyles)(node);
165
- let str = '';
166
- for (const key in style) {
167
- let useKey = key;
168
- const rawValue = style[key];
169
- let value = `"${rawValue}"`;
170
- if (['padding', 'margin'].includes(key)) {
171
- // TODO: throw error if calc()
172
- value = parseFloat(rawValue);
173
- str += `\n.${useKey}(${value})`;
121
+ else {
122
+ // Add default initialization based on type
123
+ switch (swiftType) {
124
+ case 'String':
125
+ stateDeclaration += ' = ""';
126
+ break;
127
+ case 'Bool':
128
+ stateDeclaration += ' = false';
129
+ break;
130
+ case 'Double':
131
+ case 'Int':
132
+ stateDeclaration += ' = 0';
133
+ break;
134
+ case 'Array<String>':
135
+ case '[String]':
136
+ stateDeclaration += ' = []';
137
+ break;
138
+ default:
139
+ if (swiftType.includes('Array') || swiftType.includes('[')) {
140
+ stateDeclaration += ' = []';
141
+ }
142
+ else if (swiftType !== 'Any' && swiftType !== 'Void') {
143
+ stateDeclaration += '/* initialize with appropriate default */';
144
+ }
145
+ }
174
146
  }
175
- else if (key === 'color') {
176
- useKey = 'foregroundColor';
177
- // TODO: convert to RBG and use Color(red: ..., ....)
147
+ return stateDeclaration;
148
+ })
149
+ .join('\n ');
150
+ // Generate state function variables with inline closure assignment
151
+ const functionStateProperties = [];
152
+ Object.entries(json.state)
153
+ .filter(([_, value]) => {
154
+ return ((value === null || value === void 0 ? void 0 : value.type) === 'method' ||
155
+ ((value === null || value === void 0 ? void 0 : value.code) && (value.code.includes('function') || value.code.includes('=>'))));
156
+ })
157
+ .forEach(([key, value]) => {
158
+ if (!(value === null || value === void 0 ? void 0 : value.code)) {
159
+ // Handle empty function with inline closure
160
+ functionStateProperties.push(`private var ${key}: () -> Void = { () in /* Empty function */ }`);
161
+ return;
178
162
  }
179
- else {
180
- console.warn(`Styling key "${key}" is not supported`);
163
+ // Convert the JS function to Swift
164
+ const processedCode = (0, helpers_1.stripStateAndProps)({ json, options })(value.code);
165
+ const { swiftCode, signature } = (0, helpers_1.convertJsFunctionToSwift)(processedCode, `_${key}`);
166
+ // Parse signature to get parameter list and return type
167
+ const signatureMatch = signature.match(/func _([^(]+)\(([^)]*)\) -> ([^{]+)/);
168
+ if (signatureMatch) {
169
+ const [, funcName, params, returnType] = signatureMatch;
170
+ // Create the function type for the state variable
171
+ const paramTypes = params
172
+ ? params
173
+ .split(',')
174
+ .map((p) => { var _a; return ((_a = p.trim().split(':')[1]) === null || _a === void 0 ? void 0 : _a.trim()) || 'Any'; })
175
+ .join(', ')
176
+ : '';
177
+ const functionType = params
178
+ ? `(${paramTypes}) -> ${returnType.trim()}`
179
+ : `() -> ${returnType.trim()}`;
180
+ // Extract function body from swiftCode
181
+ const bodyMatch = swiftCode.match(/{\s*([\s\S]*?)\s*}/);
182
+ const functionBody = bodyMatch ? bodyMatch[1].trim() : '/* Empty function body */';
183
+ // Build closure syntax for inline assignment
184
+ const closureSyntax = params
185
+ ? `{ (${params}) -> ${returnType.trim()} in\n ${functionBody}\n }`
186
+ : `{ () -> ${returnType.trim()} in\n ${functionBody}\n }`;
187
+ // Add the state variable declaration with inline closure assignment
188
+ functionStateProperties.push(`var ${key}: ${functionType} = ${closureSyntax}`);
181
189
  }
182
- }
183
- return str;
184
- }
185
- function getJsSource(json, options) {
186
- const str = `const state = new Proxy(${(0, get_state_object_string_1.getStateObjectStringFromComponent)(json)}, {
187
- set: (target, key, value) => {
188
- const returnVal = Reflect.set(target, key, value);
189
- update();
190
- return returnVal;
191
- }
192
- });`;
193
- if (options.prettier === false) {
194
- return str.trim();
195
- }
196
- else {
197
- return (0, try_prettier_format_1.tryPrettierFormat)(str, 'typescript').trim();
198
- }
199
- }
200
- const processBinding = (str, options) => {
201
- // Use triple quotes for multiline strings or strings including '"'
202
- if (str.includes('\n') || str.includes('"')) {
203
- return `eval(code: """
204
- ${str}
205
- """)`;
206
- }
207
- // Use double quotes for simple strings
208
- return `eval(code: "${str}")`;
209
- };
210
- function componentHasDynamicData(json) {
211
- const hasState = (0, state_1.checkHasState)(json);
212
- if (hasState) {
213
- return true;
214
- }
215
- let found = false;
216
- (0, legacy_1.default)(json).forEach(function (node) {
217
- if ((0, is_mitosis_node_1.isMitosisNode)(node)) {
218
- if (Object.keys(node.bindings).filter((item) => item !== 'css').length) {
219
- found = true;
220
- this.stop();
221
- }
190
+ else {
191
+ // Fallback if signature parsing fails
192
+ functionStateProperties.push(`var ${key}: () -> Void = { () in /* Could not parse function */ }`);
222
193
  }
223
194
  });
224
- return found;
225
- }
226
- function mapDataForSwiftCompatability(json) {
227
- let inputIndex = 0;
228
- json.meta.inputNames = json.meta.inputNames || [];
229
- (0, legacy_1.default)(json).forEach(function (node) {
230
- var _a;
231
- if ((0, is_mitosis_node_1.isMitosisNode)(node)) {
232
- if (node.name === 'input') {
233
- if (!Object.keys(node.bindings).filter((item) => item !== 'css').length) {
234
- return;
235
- }
236
- if (!node.properties.$name) {
237
- node.properties.$name = `input${++inputIndex}`;
238
- }
239
- json.meta.inputNames[node.properties.$name] =
240
- ((_a = node.bindings.value) === null || _a === void 0 ? void 0 : _a.code) || '';
241
- }
195
+ // Process lifecycle methods
196
+ const lifecycleMethods = [];
197
+ // Only add onInit if needed and if there are no function state properties
198
+ // (to avoid duplicate initializers)
199
+ if ((_b = json.hooks.onInit) === null || _b === void 0 ? void 0 : _b.code) {
200
+ lifecycleMethods.push((0, dedent_1.dedent) `
201
+ init() {
202
+ ${json.hooks.onInit.code}
242
203
  }
243
- });
244
- }
245
- function getInputBindings(json, options) {
246
- let str = '';
247
- const inputNames = json.meta.inputNames;
248
- if (!inputNames) {
249
- return str;
204
+ `);
250
205
  }
251
- for (const item in inputNames) {
252
- str += `\n@State private var ${item}: String = ""`;
253
- }
254
- return str;
255
- }
256
- const componentToSwift = (options = {}) => ({ component }) => {
257
- const json = (0, fast_clone_1.fastClone)(component);
258
- mapDataForSwiftCompatability(json);
259
- const hasDyanmicData = componentHasDynamicData(json);
260
- let children = json.children.map((item) => blockToSwift(item, options)).join('\n');
261
- const hasInputNames = Object.keys(json.meta.inputNames || {}).length > 0;
206
+ // Generate SwiftUI component
262
207
  let str = (0, dedent_1.dedent) `
263
- import SwiftUI
264
- ${!hasDyanmicData
265
- ? ''
266
- : `import JavaScriptCore
267
-
268
- final class UpdateTracker: ObservableObject {
269
- @Published var value = 0;
270
-
271
- func update() {
272
- value += 1
273
- }
274
- }
275
- `}
276
-
277
- struct ${component.name}: View {
278
- ${!hasDyanmicData
279
- ? ''
280
- : `
281
- @ObservedObject var updateTracker = UpdateTracker()
282
- private var jsContext = JSContext()
283
- ${getInputBindings(json, options)}
208
+ import SwiftUI
284
209
 
285
- func eval(code: String) -> JSValue! {
286
- return jsContext?.evaluateScript(code)
210
+ struct ${componentName}: View {
211
+ ${props
212
+ .map((prop) => {
213
+ var _a, _b, _c, _d;
214
+ const propType = ((_b = (_a = json.props) === null || _a === void 0 ? void 0 : _a[prop]) === null || _b === void 0 ? void 0 : _b.propertyType) || 'Any';
215
+ const swiftType = (0, helpers_1.getSwiftType)(propType);
216
+ return `let ${prop}: ${swiftType}${((_d = (_c = json.props) === null || _c === void 0 ? void 0 : _c[prop]) === null || _d === void 0 ? void 0 : _d.optional) ? '?' : ''}`;
217
+ })
218
+ .join('\n ')}
219
+
220
+ ${stateProperties}
221
+ ${functionStateProperties.length > 0
222
+ ? '\n // Function state variables\n ' + functionStateProperties.join('\n ')
223
+ : ''}
224
+
225
+ var body: some View {
226
+ ${json.children
227
+ .map((item) => (0, blocks_1.blockToSwift)({
228
+ json: item,
229
+ options: options,
230
+ parentComponent: json,
231
+ }))
232
+ .join('\n')}
233
+ ${lifecycleMethods.filter((method) => method.startsWith('.')).join('\n ')}
287
234
  }
288
-
289
- ${!hasInputNames
290
- ? ''
291
- : `
292
- func setComputedState() {
293
- ${Object.keys(json.meta.inputNames || {})
294
- .map((item) => {
295
- return `${item} = ${processBinding(json.meta.inputNames[item], options)}.toString()!`;
296
- })
297
- .join('\n')}
298
- }`}
299
-
300
- init() {
301
- let jsSource = """
302
- ${getJsSource(json, options)}
303
- """
304
- jsContext?.exceptionHandler = { context, exception in
305
- print("JS Error: \\(exception!)")
235
+
236
+ ${lifecycleMethods.filter((method) => !method.startsWith('.')).join('\n ')}
237
+ }
238
+ `;
239
+ // Add preview if enabled
240
+ if (options.includePreview) {
241
+ str += (0, dedent_1.dedent) `
242
+ \n
243
+ #if DEBUG
244
+ struct ${componentName}_Previews: PreviewProvider {
245
+ static var previews: some View {
246
+ ${componentName}(
247
+ ${props
248
+ .map((prop) => {
249
+ var _a, _b, _c, _d;
250
+ const propType = ((_b = (_a = json.props) === null || _a === void 0 ? void 0 : _a[prop]) === null || _b === void 0 ? void 0 : _b.propertyType) || 'Any';
251
+ const swiftType = (0, helpers_1.getSwiftType)(propType);
252
+ // Generate appropriate preview values based on type
253
+ let previewValue = '';
254
+ switch (swiftType) {
255
+ case 'String':
256
+ previewValue = '"Preview"';
257
+ break;
258
+ case 'Bool':
259
+ previewValue = 'false';
260
+ break;
261
+ case 'Double':
262
+ case 'Int':
263
+ previewValue = '0';
264
+ break;
265
+ default:
266
+ if ((_d = (_c = json.props) === null || _c === void 0 ? void 0 : _c[prop]) === null || _d === void 0 ? void 0 : _d.optional) {
267
+ previewValue = 'nil';
268
+ }
269
+ else {
270
+ previewValue = '/* provide preview value */';
271
+ }
272
+ }
273
+ return `${prop}: ${previewValue}`;
274
+ })
275
+ .join(',\n ')}
276
+ )
306
277
  }
307
-
308
- let updateRef = updateTracker.update
309
- let updateFn : @convention(block) () -> Void = { updateRef() }
310
- jsContext?.setObject(updateFn, forKeyedSubscript: "update" as NSString)
311
-
312
- jsContext?.evaluateScript(jsSource)
313
- }
314
- `.trim()}
315
-
316
- var body: some View {
317
- VStack {
318
- ${children}
319
- }${!hasInputNames
320
- ? ''
321
- : `
322
- .onAppear {
323
- setComputedState()
324
278
  }
325
- `}
326
- }
327
- }
328
- `;
329
- if (options.prettier !== false) {
330
- str = (0, generic_format_1.format)(str);
279
+ #endif
280
+ `;
331
281
  }
282
+ str = (0, plugins_1.runPreCodePlugins)({ json, code: str, plugins: options.plugins });
283
+ str = (0, generic_format_1.format)(str);
284
+ str = (0, plugins_1.runPostCodePlugins)({ json, code: str, plugins: options.plugins });
332
285
  return str;
333
286
  };
334
287
  exports.componentToSwift = componentToSwift;
@@ -0,0 +1,42 @@
1
+ import { MitosisComponent } from '../../types/mitosis-component';
2
+ import { MitosisNode } from '../../types/mitosis-node';
3
+ import { ToSwiftOptions } from './types';
4
+ export declare const convertConsoleLogToPrint: (code: string) => string;
5
+ export declare const ensureSwiftStringFormat: (code: string) => string;
6
+ export declare const stripStateAndProps: ({ json, options, }: {
7
+ json: MitosisComponent;
8
+ options: ToSwiftOptions;
9
+ }) => (code: string) => string;
10
+ export declare const getSwiftType: (type: string | undefined) => string;
11
+ export declare const jsxElementToSwiftUIView: (tagName: string) => string;
12
+ export declare const cssToSwiftUIModifiers: (style: Record<string, string>) => string[];
13
+ export declare const getStatePropertyTypeAnnotation: (propertyType: string | undefined, type: string | undefined) => string;
14
+ export declare const getEventHandlerName: (eventName: string) => string;
15
+ export declare const needsScrollView: (json: MitosisNode) => boolean;
16
+ export declare const isForEachBlock: (json: MitosisNode) => boolean;
17
+ export declare const getForEachParams: (json: MitosisNode, processCode: (code: string) => string) => {
18
+ collection: string;
19
+ itemName: string;
20
+ indexName: string | null;
21
+ };
22
+ export declare const camelToSnakeCase: (str: string) => string;
23
+ export declare const getBindingType: (key: string) => string;
24
+ /**
25
+ * Extract function signature information from JavaScript function code
26
+ */
27
+ export declare const extractFunctionSignature: (code: string) => {
28
+ name: string;
29
+ params: {
30
+ name: string;
31
+ type: string;
32
+ }[];
33
+ returnType: string;
34
+ body: string;
35
+ };
36
+ /**
37
+ * Convert JavaScript function code to Swift function syntax
38
+ */
39
+ export declare const convertJsFunctionToSwift: (code: string, functionName?: string) => {
40
+ swiftCode: string;
41
+ signature: string;
42
+ };