@builder.io/mitosis 0.5.26 → 0.5.28

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.
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.componentToAngular = exports.blockToAngular = void 0;
29
+ exports.componentToAngular = void 0;
30
30
  const html_tags_1 = require("../../constants/html_tags");
31
31
  const bindings_1 = require("../../helpers/bindings");
32
32
  const dedent_1 = require("../../helpers/dedent");
@@ -46,7 +46,6 @@ const is_upper_case_1 = require("../../helpers/is-upper-case");
46
46
  const map_refs_1 = require("../../helpers/map-refs");
47
47
  const merge_options_1 = require("../../helpers/merge-options");
48
48
  const process_code_1 = require("../../helpers/plugins/process-code");
49
- const remove_surrounding_block_1 = require("../../helpers/remove-surrounding-block");
50
49
  const render_imports_1 = require("../../helpers/render-imports");
51
50
  const replace_identifiers_1 = require("../../helpers/replace-identifiers");
52
51
  const slots_1 = require("../../helpers/slots");
@@ -56,8 +55,6 @@ const collect_css_1 = require("../../helpers/styles/collect-css");
56
55
  const helpers_1 = require("../../helpers/styles/helpers");
57
56
  const traverse_nodes_1 = require("../../helpers/traverse-nodes");
58
57
  const plugins_1 = require("../../modules/plugins");
59
- const symbol_processor_1 = require("../../symbols/symbol-processor");
60
- const mitosis_node_1 = require("../../types/mitosis-node");
61
58
  const babel = __importStar(require("@babel/core"));
62
59
  const function_1 = require("fp-ts/lib/function");
63
60
  const lodash_1 = require("lodash");
@@ -67,36 +64,12 @@ const is_children_1 = __importDefault(require("../../helpers/is-children"));
67
64
  const on_mount_1 = require("../helpers/on-mount");
68
65
  const helpers_2 = require("./helpers");
69
66
  const types_1 = require("./types");
67
+ const dash_case_1 = require("../../helpers/dash-case");
70
68
  const event_handlers_1 = require("../../helpers/event-handlers");
71
- const parse_selector_1 = require("./parse-selector");
69
+ const hooks_1 = require("../../generators/angular/helpers/hooks");
70
+ const attribute_passing_1 = require("../../helpers/web-components/attribute-passing");
71
+ const blocks_1 = require("./blocks");
72
72
  const { types } = babel;
73
- const mappers = {
74
- Fragment: (root, json, options, blockOptions) => {
75
- return `<ng-container>${json.children
76
- .map((item) => (0, exports.blockToAngular)({ root, json: item, options, blockOptions }))
77
- .join('\n')}</ng-container>`;
78
- },
79
- Slot: (root, json, options, blockOptions) => {
80
- const renderChildren = () => {
81
- var _a;
82
- return (_a = json.children) === null || _a === void 0 ? void 0 : _a.map((item) => (0, exports.blockToAngular)({ root, json: item, options, blockOptions })).join('\n');
83
- };
84
- return `<ng-content ${Object.entries({ ...json.bindings, ...json.properties })
85
- .map(([binding, value]) => {
86
- if (value && binding === 'name') {
87
- const selector = (0, function_1.pipe)((0, lodash_1.isString)(value) ? value : value.code, slots_1.stripSlotPrefix, lodash_1.kebabCase);
88
- return `select="[${selector}]"`;
89
- }
90
- })
91
- .join('\n')}>${Object.entries(json.bindings)
92
- .map(([binding, value]) => {
93
- if (value && binding !== 'name') {
94
- return value.code;
95
- }
96
- })
97
- .join('\n')}${renderChildren()}</ng-content>`;
98
- },
99
- };
100
73
  const preprocessCssAsJson = (json) => {
101
74
  (0, legacy_1.default)(json).forEach((item) => {
102
75
  var _a, _b;
@@ -123,375 +96,13 @@ ${content}
123
96
  })
124
97
  export class ${name}Module {}`;
125
98
  };
126
- // TODO: Maybe in the future allow defining `string | function` as values
127
- const BINDINGS_MAPPER = {
128
- innerHTML: 'innerHTML',
129
- style: 'ngStyle',
130
- };
131
- const handleObjectBindings = (code) => {
132
- let objectCode = code.replace(/^{/, '').replace(/}$/, '');
133
- objectCode = objectCode.replace(/\/\/.*\n/g, '');
134
- let temp = objectCode;
135
- //STEP 1. remove spread operator for expressions like '{ ...objectName }' and replace them with object name, example {...obj} => obj
136
- temp = temp.replace(/\{\s*\.\.\.(\w+)\s*}/g, '$1');
137
- //STEP 2. remove all remaining spread operators that could be nested somewhere deeper, example { ...obj, field1: value1 } => { obj, field1: value1 }
138
- temp = temp.replace(/\.\.\./g, '');
139
- //STEP 3. deal with consequences of STEP 2 - for all left field assignments we create new objects provided to useObjectWrapper,
140
- //and we get rid of surrounding brackets of the initial input value, example {...obj1,test:true,...obj2} => obj1, {test: true}, obj2
141
- temp = temp.replace(/(\s*\w+\s*:\s*((["'].+["'])|(\[.+])|([\w.]+)))(,|[\n\s]*)/g, `{ $1 },`);
142
- // handle template strings
143
- if (temp.includes('`')) {
144
- // template str
145
- let str = temp.match(/`[^`]*`/g);
146
- let values = str && str[0].match(/\${[^}]*}/g);
147
- let forValues = values === null || values === void 0 ? void 0 : values.map((val) => val.slice(2, -1)).join(' + ');
148
- if (str && forValues) {
149
- temp = temp.replace(str[0], forValues);
150
- }
151
- }
152
- return temp;
153
- };
154
- const processCodeBlockInTemplate = (code) => {
155
- // contains helper calls as Angular doesn't support JS expressions in templates
156
- if (code.startsWith('{') && code.includes('...')) {
157
- // Objects cannot be spread out directly in Angular so we need to use `useObjectWrapper`
158
- return `useObjectWrapper(${handleObjectBindings(code)})`;
159
- }
160
- else if (code.startsWith('Object.values')) {
161
- let stripped = code.replace('Object.values', '');
162
- return `useObjectDotValues${stripped}`;
163
- }
164
- else if (code.includes('JSON.stringify')) {
165
- let obj = code.match(/JSON.stringify\((.*)\)/);
166
- return `useJsonStringify(${obj})`;
167
- }
168
- else if (code.includes(' as ')) {
169
- const asIndex = code.indexOf('as');
170
- const asCode = code.slice(0, asIndex - 1);
171
- return `$any${asCode})`;
172
- }
173
- else {
174
- return `${code}`;
175
- }
176
- };
177
- const processEventBinding = (key, code, nodeName, customArg) => {
178
- let event = key.replace('on', '');
179
- event = event.charAt(0).toLowerCase() + event.slice(1);
180
- // TODO: proper babel transform to replace. Util for this
181
- const eventName = customArg;
182
- const regexp = new RegExp('(^|\\n|\\r| |;|\\(|\\[|!)' + eventName + '(\\?\\.|\\.|\\(| |;|\\)|$)', 'g');
183
- const replacer = '$1$event$2';
184
- const finalValue = (0, remove_surrounding_block_1.removeSurroundingBlock)(code.replace(regexp, replacer));
185
- return {
186
- event,
187
- value: finalValue,
188
- };
189
- };
190
- const stringifyBinding = (node, options, blockOptions) => ([key, binding]) => {
191
- var _a, _b;
192
- if (key.startsWith('$') || key.startsWith('"') || key === 'key') {
193
- return;
194
- }
195
- if ((binding === null || binding === void 0 ? void 0 : binding.type) === 'spread') {
196
- return;
197
- }
198
- const keyToUse = BINDINGS_MAPPER[key] || key;
199
- const { code, arguments: cusArgs = ['event'] } = binding;
200
- // TODO: proper babel transform to replace. Util for this
201
- if ((0, event_handlers_1.checkIsEvent)(keyToUse)) {
202
- const { event, value } = processEventBinding(keyToUse, code, node.name, cusArgs[0]);
203
- // native events are all lowerCased
204
- const lowerCaseEvent = event.toLowerCase();
205
- const eventKey = (0, event_handlers_1.checkIsBindingNativeEvent)(event) ||
206
- ((_a = blockOptions.nativeEvents) === null || _a === void 0 ? void 0 : _a.find((nativeEvent) => nativeEvent === keyToUse || nativeEvent === event || nativeEvent === lowerCaseEvent))
207
- ? lowerCaseEvent
208
- : event;
209
- return ` (${eventKey})="${value}"`;
210
- }
211
- else if (keyToUse === 'class') {
212
- return ` [class]="${code}" `;
213
- }
214
- else if (keyToUse === 'ref' || keyToUse === 'spreadRef') {
215
- return ` #${code} `;
216
- }
217
- else if ((html_tags_1.VALID_HTML_TAGS.includes(node.name.trim()) || keyToUse.includes('-')) &&
218
- !((_b = blockOptions.nativeAttributes) === null || _b === void 0 ? void 0 : _b.includes(keyToUse)) &&
219
- !Object.values(BINDINGS_MAPPER).includes(keyToUse)) {
220
- // standard html elements need the attr to satisfy the compiler in many cases: eg: svg elements and [fill]
221
- return ` [attr.${keyToUse}]="${code}" `;
222
- }
223
- else {
224
- const codeToUse = options.state === 'inline-with-wrappers' ? processCodeBlockInTemplate(code) : code;
225
- return `[${keyToUse}]="${codeToUse}"`;
226
- }
227
- };
228
- const handleNgOutletBindings = (node, options) => {
229
- var _a;
230
- let allProps = '';
231
- for (const key in node.properties) {
232
- if (key.startsWith('$')) {
233
- continue;
234
- }
235
- if (key === 'key') {
236
- continue;
237
- }
238
- const value = node.properties[key];
239
- allProps += `${key}: '${value}', `;
240
- }
241
- for (const key in node.bindings) {
242
- if (key.startsWith('"')) {
243
- continue;
244
- }
245
- if (key.startsWith('$')) {
246
- continue;
247
- }
248
- let { code, arguments: cusArgs = ['event'] } = node.bindings[key];
249
- if (options.state === 'class-properties') {
250
- code = `this.${code}`;
251
- if (((_a = node.bindings[key]) === null || _a === void 0 ? void 0 : _a.type) === 'spread') {
252
- allProps += `...${code}, `;
253
- continue;
254
- }
255
- }
256
- let keyToUse = key.includes('-') ? `'${key}'` : key;
257
- keyToUse = keyToUse.replace('state.', '').replace('props.', '');
258
- if ((0, event_handlers_1.checkIsEvent)(key)) {
259
- const { event, value } = processEventBinding(key, code, node.name, cusArgs[0]);
260
- allProps += `on${event.charAt(0).toUpperCase() + event.slice(1)}: ${value.replace(/\(.*?\)/g, '')}.bind(this), `;
261
- }
262
- else {
263
- const codeToUse = options.state === 'inline-with-wrappers' ? processCodeBlockInTemplate(code) : code;
264
- allProps += `${keyToUse}: ${codeToUse}, `;
265
- }
266
- }
267
- if (allProps.endsWith(', ')) {
268
- allProps = allProps.slice(0, -2);
269
- }
270
- if (allProps.startsWith(', ')) {
271
- allProps = allProps.slice(2);
272
- }
273
- return allProps;
274
- };
275
- const blockToAngular = ({ root, json, options = {}, blockOptions = {
276
- nativeAttributes: [],
277
- nativeEvents: [],
278
- }, }) => {
279
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
280
- const childComponents = (blockOptions === null || blockOptions === void 0 ? void 0 : blockOptions.childComponents) || [];
281
- if (mappers[json.name]) {
282
- return mappers[json.name](root, json, options, blockOptions);
283
- }
284
- if ((0, is_children_1.default)({ node: json })) {
285
- return `<ng-content></ng-content>`;
286
- }
287
- if (json.properties._text) {
288
- return json.properties._text;
289
- }
290
- const textCode = (_a = json.bindings._text) === null || _a === void 0 ? void 0 : _a.code;
291
- if (textCode) {
292
- if ((0, slots_1.isSlotProperty)(textCode)) {
293
- return `<ng-content select="[${(0, slots_1.toKebabSlot)(textCode)}]"></ng-content>`;
294
- }
295
- if (textCode.includes('JSON.stringify')) {
296
- const obj = textCode.replace(/JSON.stringify\(\s*(\w+)\s*,?.*\)/, '$1');
297
- return `{{${obj} | json}}`;
298
- }
299
- return `{{${textCode}}}`;
300
- }
301
- let str = '';
302
- if ((0, mitosis_node_1.checkIsForNode)(json)) {
303
- const indexName = json.scope.indexName;
304
- const forName = json.scope.forName;
305
- // Check if "key" is present for the first child of the for loop
306
- if ((0, helpers_2.hasFirstChildKeyAttribute)(json)) {
307
- const fnIndex = ((_b = root.meta) === null || _b === void 0 ? void 0 : _b._trackByForIndex) || 0;
308
- const trackByFnName = `trackBy${forName ? forName.charAt(0).toUpperCase() + forName.slice(1) : ''}${fnIndex}`;
309
- root.meta._trackByForIndex = fnIndex + 1;
310
- let code = (_c = json.children[0].bindings.key) === null || _c === void 0 ? void 0 : _c.code;
311
- root.state[trackByFnName] = {
312
- code: `${trackByFnName}(${indexName !== null && indexName !== void 0 ? indexName : '_'}, ${forName}) { return ${code}; }`,
313
- type: 'method',
314
- };
315
- str += `<ng-container *ngFor="let ${forName !== null && forName !== void 0 ? forName : '_'} of ${(_d = json.bindings.each) === null || _d === void 0 ? void 0 : _d.code}${indexName ? `; index as ${indexName}` : ''}; trackBy: ${trackByFnName}">`;
316
- }
317
- else {
318
- str += `<ng-container *ngFor="let ${forName !== null && forName !== void 0 ? forName : '_'} of ${(_e = json.bindings.each) === null || _e === void 0 ? void 0 : _e.code}${indexName ? `; index as ${indexName}` : ''}">`;
319
- }
320
- str += json.children
321
- .map((item) => (0, exports.blockToAngular)({ root, json: item, options, blockOptions }))
322
- .join('\n');
323
- str += `</ng-container>`;
324
- }
325
- else if (json.name === 'Show') {
326
- let condition = (_f = json.bindings.when) === null || _f === void 0 ? void 0 : _f.code;
327
- if (options.state === 'inline-with-wrappers' && (condition === null || condition === void 0 ? void 0 : condition.includes('typeof'))) {
328
- let wordAfterTypeof = condition.split('typeof')[1].trim().split(' ')[0];
329
- condition = condition.replace(`typeof ${wordAfterTypeof}`, `useTypeOf(${wordAfterTypeof})`);
330
- }
331
- str += `<ng-container *ngIf="${condition}">`;
332
- str += json.children
333
- .map((item) => (0, exports.blockToAngular)({ root, json: item, options, blockOptions }))
334
- .join('\n');
335
- str += `</ng-container>`;
336
- // else condition
337
- if ((0, is_mitosis_node_1.isMitosisNode)((_g = json.meta) === null || _g === void 0 ? void 0 : _g.else)) {
338
- str += `<ng-container *ngIf="!(${condition})">`;
339
- str += (0, exports.blockToAngular)({ root, json: json.meta.else, options, blockOptions });
340
- str += `</ng-container>`;
341
- }
342
- }
343
- else if (json.name.includes('.')) {
344
- const elSelector = childComponents.find((impName) => impName === json.name)
345
- ? (0, lodash_1.kebabCase)(json.name)
346
- : json.name;
347
- let allProps = handleNgOutletBindings(json, options);
348
- if (options.state === 'class-properties') {
349
- const inputsPropsStateName = `mergedInputs_${(0, symbol_processor_1.hashCodeAsString)(allProps)}`;
350
- root.state[inputsPropsStateName] = {
351
- code: '{}' + (options.typescript ? ' as any' : ''),
352
- type: 'property',
353
- };
354
- if (!((_h = root.hooks.onInit) === null || _h === void 0 ? void 0 : _h.code.includes(inputsPropsStateName))) {
355
- (0, helpers_2.addCodeToOnInit)(root, `this.${inputsPropsStateName} = {${allProps}};`);
356
- }
357
- if (!((_j = root.hooks.onUpdate) === null || _j === void 0 ? void 0 : _j.map((hook) => hook.code).join('').includes(inputsPropsStateName))) {
358
- (0, helpers_2.addCodeToOnUpdate)(root, `this.${inputsPropsStateName} = {${allProps}};`);
359
- }
360
- allProps = `${inputsPropsStateName}`;
361
- }
362
- else {
363
- allProps = `{ ${allProps} }`;
364
- }
365
- str += `<ng-container *ngComponentOutlet="
366
- ${elSelector.replace('state.', '').replace('props.', '')};
367
- inputs: ${allProps};
368
- content: myContent;
369
- "> `;
370
- str += `</ng-container>`;
371
- }
372
- else {
373
- let element, classNames = [], attributes;
374
- const isComponent = childComponents.find((impName) => impName === json.name);
375
- if (isComponent) {
376
- const selector = json.meta.selector || (blockOptions === null || blockOptions === void 0 ? void 0 : blockOptions.selector);
377
- if (selector) {
378
- try {
379
- ({ element, classNames, attributes } = (0, parse_selector_1.parse)(`${selector}`));
380
- }
381
- catch (_r) {
382
- element = (0, lodash_1.kebabCase)(json.name);
383
- }
384
- }
385
- else {
386
- element = (0, lodash_1.kebabCase)(json.name);
387
- }
388
- }
389
- else {
390
- element = json.name;
391
- }
392
- str += `<${element} `;
393
- // TODO: merge with existing classes/bindings
394
- if (classNames.length) {
395
- str += `class="${classNames.join(' ')}" `;
396
- }
397
- // TODO: Merge with existing properties
398
- if (attributes) {
399
- Object.entries(attributes).forEach(([key, value]) => {
400
- if (value) {
401
- str += `${key}=${JSON.stringify(value)} `;
402
- }
403
- else {
404
- str += `${key} `;
405
- }
406
- });
407
- }
408
- for (const key in json.properties) {
409
- if (key.startsWith('$')) {
410
- continue;
411
- }
412
- const value = json.properties[key];
413
- str += ` ${key}="${value}" `;
414
- }
415
- for (const key in json.bindings) {
416
- if (((_k = json.bindings[key]) === null || _k === void 0 ? void 0 : _k.type) === 'spread' && html_tags_1.VALID_HTML_TAGS.includes(json.name.trim())) {
417
- if (((_l = json.bindings[key]) === null || _l === void 0 ? void 0 : _l.code) === 'this') {
418
- // if its an arbitrary { ...props } spread then we skip because Angular needs a named prop to be defined
419
- continue;
420
- }
421
- let refName = '';
422
- if ((_m = json.bindings['spreadRef']) === null || _m === void 0 ? void 0 : _m.code) {
423
- refName = json.bindings['spreadRef'].code;
424
- }
425
- else {
426
- const spreadRefIndex = root.meta._spreadRefIndex || 0;
427
- refName = `elRef${spreadRefIndex}`;
428
- root.meta._spreadRefIndex = spreadRefIndex + 1;
429
- json.bindings['spreadRef'] = (0, bindings_1.createSingleBinding)({ code: refName });
430
- root.refs[refName] = { argument: '' };
431
- }
432
- json.bindings['spreadRef'] = (0, bindings_1.createSingleBinding)({ code: refName });
433
- root.refs[refName] = { argument: '' };
434
- root.meta.onViewInit = (root.meta.onViewInit || { code: '' });
435
- let spreadCode = '';
436
- let changesCode = '';
437
- if ((_o = json.bindings[key]) === null || _o === void 0 ? void 0 : _o.code.startsWith('{')) {
438
- json.meta._spreadStateRef = json.meta._spreadStateRef || 0;
439
- const name = `${refName}_state_${json.meta._spreadStateRef}`;
440
- json.meta._spreadStateRef = json.meta._spreadStateRef + 1;
441
- (0, helpers_2.makeReactiveState)(root, name, `this.${name} = ${(_p = json.bindings[key]) === null || _p === void 0 ? void 0 : _p.code};`);
442
- spreadCode = `this.${name}`;
443
- changesCode = `changes['${spreadCode.replace('this.', '')}']?.currentValue`;
444
- }
445
- else {
446
- spreadCode = `${(_q = json.bindings[key]) === null || _q === void 0 ? void 0 : _q.code}`;
447
- changesCode = `changes['${spreadCode.replace('this.', '')}']?.currentValue`;
448
- }
449
- if (!root.compileContext) {
450
- root.compileContext = {
451
- angular: {
452
- hooks: {
453
- ngAfterViewInit: {
454
- code: '',
455
- },
456
- },
457
- },
458
- };
459
- }
460
- root.compileContext.angular.hooks.ngAfterViewInit.code += `\nthis.setAttributes(this.${refName}?.nativeElement, ${spreadCode});`;
461
- (0, helpers_2.addCodeToOnUpdate)(root, `this.setAttributes(this.${refName}?.nativeElement, ${spreadCode}${changesCode ? `, ${changesCode}` : ''});`);
462
- if (!root.state['setAttributes']) {
463
- root.state['setAttributes'] = {
464
- code: (0, helpers_2.HELPER_FUNCTIONS)(options === null || options === void 0 ? void 0 : options.typescript).setAttributes,
465
- type: 'method',
466
- };
467
- }
468
- }
469
- }
470
- const stringifiedBindings = Object.entries(json.bindings)
471
- .map(stringifyBinding(json, options, blockOptions))
472
- .join('');
473
- str += stringifiedBindings;
474
- if (html_tags_1.SELF_CLOSING_HTML_TAGS.has(json.name)) {
475
- return str + ' />';
476
- }
477
- str += '>';
478
- if (json.children) {
479
- str += json.children
480
- .map((item) => (0, exports.blockToAngular)({ root, json: item, options, blockOptions }))
481
- .join('\n');
482
- }
483
- str += `</${element}>`;
484
- }
485
- return str;
486
- };
487
- exports.blockToAngular = blockToAngular;
488
99
  const traverseToGetAllDynamicComponents = (json, options, blockOptions) => {
489
100
  const components = new Set();
490
101
  let dynamicTemplate = '';
491
102
  (0, legacy_1.default)(json).forEach((item) => {
492
103
  if ((0, is_mitosis_node_1.isMitosisNode)(item) && item.name.includes('.') && item.name.split('.').length === 2) {
493
104
  const children = item.children
494
- .map((child) => (0, exports.blockToAngular)({ root: json, json: child, options, blockOptions }))
105
+ .map((child) => (0, blocks_1.blockToAngular)({ root: json, json: child, options, blockOptions }))
495
106
  .join('\n');
496
107
  dynamicTemplate = `<ng-template #${item.name.split('.')[1].toLowerCase() + 'Template'}>${children}</ng-template>`;
497
108
  components.add(item.name);
@@ -579,7 +190,7 @@ const handleBindings = (json, item, index, forName, indexName) => {
579
190
  else if ((_c = item.bindings[key]) === null || _c === void 0 ? void 0 : _c.code) {
580
191
  if (((_d = item.bindings[key]) === null || _d === void 0 ? void 0 : _d.type) !== 'spread' && !(0, event_handlers_1.checkIsEvent)(key)) {
581
192
  json.state[newBindingName] = { code: 'null', type: 'property' };
582
- (0, helpers_2.makeReactiveState)(json, newBindingName, `this.${newBindingName} = ${item.bindings[key].code}`);
193
+ (0, hooks_1.makeReactiveState)(json, newBindingName, `this.${newBindingName} = ${item.bindings[key].code}`);
583
194
  item.bindings[key].code = `state.${newBindingName}`;
584
195
  }
585
196
  else if ((0, event_handlers_1.checkIsEvent)(key)) {
@@ -594,7 +205,7 @@ const handleBindings = (json, item, index, forName, indexName) => {
594
205
  }
595
206
  }
596
207
  else {
597
- (0, helpers_2.makeReactiveState)(json, newBindingName, `state.${newBindingName} = {...(${item.bindings[key].code})}`);
208
+ (0, hooks_1.makeReactiveState)(json, newBindingName, `state.${newBindingName} = {...(${item.bindings[key].code})}`);
598
209
  item.bindings[newBindingName] = item.bindings[key];
599
210
  item.bindings[key].code = `state.${newBindingName}`;
600
211
  delete item.bindings[key];
@@ -759,6 +370,17 @@ const componentToAngular = (userOptions = {}) => ({ component: _component }) =>
759
370
  });
760
371
  const domRefs = (0, get_refs_1.getRefs)(json);
761
372
  const jsRefs = Object.keys(json.refs).filter((ref) => !domRefs.has(ref));
373
+ const withAttributePassing = (0, attribute_passing_1.shouldAddAttributePassing)(json, options);
374
+ const rootRef = (0, attribute_passing_1.getAddAttributePassingRef)(json, options);
375
+ if (withAttributePassing) {
376
+ if (!domRefs.has(rootRef)) {
377
+ domRefs.add(rootRef);
378
+ }
379
+ (0, hooks_1.addCodeNgAfterViewInit)(json, `
380
+ const element: HTMLElement | null = this.${rootRef}?.nativeElement;
381
+ this.enableAttributePassing(element, "${(0, dash_case_1.dashCase)(json.name)}");
382
+ `);
383
+ }
762
384
  const componentsUsed = Array.from((0, get_components_used_1.getComponentsUsed)(json)).filter((item) => {
763
385
  return item.length && (0, is_upper_case_1.isUpperCase)(item[0]) && !types_1.BUILT_IN_COMPONENTS.has(item);
764
386
  });
@@ -778,10 +400,11 @@ const componentToAngular = (userOptions = {}) => ({ component: _component }) =>
778
400
  let template = json.children
779
401
  .map((item) => {
780
402
  var _a, _b, _c, _d;
781
- const tmpl = (0, exports.blockToAngular)({
403
+ const tmpl = (0, blocks_1.blockToAngular)({
782
404
  root: json,
783
405
  json: item,
784
406
  options,
407
+ rootRef: withAttributePassing && rootRef === attribute_passing_1.ROOT_REF ? rootRef : undefined, // only pass rootRef if it's not the default
785
408
  blockOptions: {
786
409
  childComponents,
787
410
  nativeAttributes: (_b = (_a = useMetadata === null || useMetadata === void 0 ? void 0 : useMetadata.angular) === null || _a === void 0 ? void 0 : _a.nativeAttributes) !== null && _b !== void 0 ? _b : [],
@@ -950,6 +573,9 @@ const componentToAngular = (userOptions = {}) => ({ component: _component }) =>
950
573
  ? `\nprivate renderer${options.typescript ? ': Renderer2' : ''},\n`
951
574
  : ''}) {}
952
575
  `}
576
+
577
+ ${withAttributePassing ? (0, attribute_passing_1.getAttributePassingString)(options.typescript) : ''}
578
+
953
579
  ${!json.hooks.onMount.length && !dynamicComponents.size && !((_l = json.hooks.onInit) === null || _l === void 0 ? void 0 : _l.code)
954
580
  ? ''
955
581
  : `ngOnInit() {
@@ -1,3 +1,9 @@
1
1
  import { ToStencilOptions } from '../../generators/stencil/types';
2
2
  import { MitosisNode } from '../../types/mitosis-node';
3
- export declare const blockToStencil: (json: MitosisNode, options: ToStencilOptions | undefined, insideJsx: boolean, childComponents: string[]) => string;
3
+ export declare const blockToStencil: ({ json, options, insideJsx, rootRef, childComponents, }: {
4
+ json: MitosisNode;
5
+ options: ToStencilOptions;
6
+ insideJsx?: boolean | undefined;
7
+ rootRef?: string | undefined;
8
+ childComponents: string[];
9
+ }) => string;
@@ -7,7 +7,7 @@ const collect_class_string_1 = require("../../generators/stencil/helpers/collect
7
7
  const filter_empty_text_nodes_1 = require("../../helpers/filter-empty-text-nodes");
8
8
  const for_1 = require("../../helpers/nodes/for");
9
9
  const mitosis_node_1 = require("../../types/mitosis-node");
10
- const blockToStencil = (json, options = {}, insideJsx, childComponents) => {
10
+ const blockToStencil = ({ json, options = {}, insideJsx, rootRef, childComponents, }) => {
11
11
  var _a, _b, _c, _d, _e, _f, _g;
12
12
  let blockName = childComponents.find((impName) => impName === json.name)
13
13
  ? (0, helpers_1.getTagName)(json.name, options)
@@ -33,7 +33,7 @@ const blockToStencil = (json, options = {}, insideJsx, childComponents) => {
33
33
  ${wrap ? '<Fragment>' : ''}
34
34
  ${json.children
35
35
  .filter(filter_empty_text_nodes_1.filterEmptyTextNodes)
36
- .map((item) => (0, exports.blockToStencil)(item, options, wrap, childComponents))
36
+ .map((item) => (0, exports.blockToStencil)({ json: item, options, insideJsx: wrap, childComponents }))
37
37
  .join('\n')}
38
38
  ${wrap ? '</Fragment>' : ''}
39
39
  ))`;
@@ -50,12 +50,16 @@ const blockToStencil = (json, options = {}, insideJsx, childComponents) => {
50
50
  ${wrap ? '<Fragment>' : ''}
51
51
  ${json.children
52
52
  .filter(filter_empty_text_nodes_1.filterEmptyTextNodes)
53
- .map((item) => (0, exports.blockToStencil)(item, options, wrap, childComponents))
53
+ .map((item) => (0, exports.blockToStencil)({ json: item, options, insideJsx: wrap, childComponents }))
54
54
  .join('\n')}
55
55
  ${wrap ? '</Fragment>' : ''}
56
56
  ) : ${!json.meta.else
57
57
  ? 'null'
58
- : `(${(0, exports.blockToStencil)(json.meta.else, options, false, childComponents)})`}`;
58
+ : `(${(0, exports.blockToStencil)({
59
+ json: json.meta.else,
60
+ options,
61
+ childComponents,
62
+ })})`}`;
59
63
  if (insideJsx) {
60
64
  return `{${expression}}`;
61
65
  }
@@ -82,8 +86,10 @@ const blockToStencil = (json, options = {}, insideJsx, childComponents) => {
82
86
  str += ` {...(${code})} `;
83
87
  }
84
88
  else if (key === 'ref') {
85
- // TODO: Add correct type here
86
- str += ` ref={(el) => ${code.startsWith('this.') ? code : `this.${code}`} = el} `;
89
+ str += ` ref={(el:any) => {
90
+ ${rootRef ? `this.${rootRef} = el` : ''}
91
+ ${code.startsWith('this.') ? code : `this.${code}`} = el}
92
+ } `;
87
93
  }
88
94
  else if ((0, helpers_1.isEvent)(key)) {
89
95
  const asyncKeyword = ((_g = json.bindings[key]) === null || _g === void 0 ? void 0 : _g.async) ? 'async ' : '';
@@ -99,7 +105,12 @@ const blockToStencil = (json, options = {}, insideJsx, childComponents) => {
99
105
  str += '>';
100
106
  if (json.children) {
101
107
  str += json.children
102
- .map((item) => (0, exports.blockToStencil)(item, options, true, childComponents))
108
+ .map((item) => (0, exports.blockToStencil)({
109
+ json: item,
110
+ options,
111
+ insideJsx: true,
112
+ childComponents,
113
+ }))
103
114
  .join('\n');
104
115
  }
105
116
  str += `</${blockName}>`;
@@ -5,6 +5,7 @@ const on_mount_1 = require("../../generators/helpers/on-mount");
5
5
  const blocks_1 = require("../../generators/stencil/blocks");
6
6
  const helpers_1 = require("../../generators/stencil/helpers");
7
7
  const get_code_processor_plugins_1 = require("../../generators/stencil/plugins/get-code-processor-plugins");
8
+ const dash_case_1 = require("../../helpers/dash-case");
8
9
  const dedent_1 = require("../../helpers/dedent");
9
10
  const fast_clone_1 = require("../../helpers/fast-clone");
10
11
  const get_child_components_1 = require("../../helpers/get-child-components");
@@ -15,6 +16,7 @@ const map_refs_1 = require("../../helpers/map-refs");
15
16
  const merge_options_1 = require("../../helpers/merge-options");
16
17
  const strip_meta_properties_1 = require("../../helpers/strip-meta-properties");
17
18
  const collect_css_1 = require("../../helpers/styles/collect-css");
19
+ const attribute_passing_1 = require("../../helpers/web-components/attribute-passing");
18
20
  const plugins_1 = require("../../modules/plugins");
19
21
  const standalone_1 = require("prettier/standalone");
20
22
  const componentToStencil = (_options = {
@@ -55,15 +57,17 @@ const componentToStencil = (_options = {
55
57
  functions: true,
56
58
  getters: true,
57
59
  });
58
- const refs = json.refs
60
+ let refs = json.refs
59
61
  ? Object.entries(json.refs)
60
- .map(([key, value]) => {
61
- var _a;
62
- return `private ${key}!: ${(_a = value.typeParameter) !== null && _a !== void 0 ? _a : 'HTMLElement'}`;
63
- })
62
+ .map(([key, value]) => { var _a; return `private ${key}!: ${(_a = value.typeParameter) !== null && _a !== void 0 ? _a : 'HTMLElement'};`; })
64
63
  .join('\n')
65
64
  : '';
66
65
  const wrap = (0, helpers_1.needsWrap)(json.children);
66
+ const withAttributePassing = !wrap && (0, attribute_passing_1.shouldAddAttributePassing)(json, options);
67
+ const rootRef = (0, attribute_passing_1.getAddAttributePassingRef)(json, options);
68
+ if (withAttributePassing && !refs.includes(rootRef)) {
69
+ refs += `\nprivate ${rootRef}!: HTMLElement;`;
70
+ }
67
71
  if (options.prettier !== false) {
68
72
  try {
69
73
  css = (0, standalone_1.format)(css, {
@@ -101,10 +105,15 @@ const componentToStencil = (_options = {
101
105
  ${(0, helpers_1.getPropsAsCode)(props, defaultProps, json.propsTypeRef)}
102
106
  ${dataString}
103
107
  ${methodsString}
108
+
109
+ ${withAttributePassing ? (0, attribute_passing_1.getAttributePassingString)(true) : ''}
104
110
 
105
- ${!json.hooks.onMount.length
106
- ? ''
107
- : `componentDidLoad() { ${(0, on_mount_1.stringifySingleScopeOnMount)(json)} }`}
111
+ ${`componentDidLoad() {
112
+ ${withAttributePassing
113
+ ? `this.enableAttributePassing(this.${rootRef}, "${(0, dash_case_1.dashCase)(json.name)}");`
114
+ : ''}
115
+ ${json.hooks.onMount.length ? (0, on_mount_1.stringifySingleScopeOnMount)(json) : ''}
116
+ }`}
108
117
  ${!((_d = json.hooks.onUnMount) === null || _d === void 0 ? void 0 : _d.code)
109
118
  ? ''
110
119
  : `disconnectedCallback() { ${json.hooks.onUnMount.code} }`}
@@ -116,7 +125,13 @@ const componentToStencil = (_options = {
116
125
  return (${wrap ? '<Host>' : ''}
117
126
 
118
127
  ${json.children
119
- .map((item) => (0, blocks_1.blockToStencil)(item, options, true, childComponents))
128
+ .map((item) => (0, blocks_1.blockToStencil)({
129
+ json: item,
130
+ options,
131
+ insideJsx: true,
132
+ childComponents,
133
+ rootRef: withAttributePassing && rootRef === attribute_passing_1.ROOT_REF ? rootRef : undefined, // only pass rootRef if it's not the default
134
+ }))
120
135
  .join('\n')}
121
136
 
122
137
  ${wrap ? '</Host>' : ''})
@@ -0,0 +1,6 @@
1
+ import { MitosisComponent } from '../../types/mitosis-component';
2
+ import { BaseTranspilerOptions } from '../../types/transpiler';
3
+ export declare const ROOT_REF = "_root";
4
+ export declare const getAttributePassingString: (typescript?: boolean) => string;
5
+ export declare const shouldAddAttributePassing: (json: MitosisComponent, options: BaseTranspilerOptions) => boolean | undefined;
6
+ export declare const getAddAttributePassingRef: (json: MitosisComponent, options: BaseTranspilerOptions) => string;