From 20ad8dc26c9aa43503dff8f6dd051e27d3d9b808 Mon Sep 17 00:00:00 2001 From: Nicolas Merget <104347736+nmerget@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:59:17 +0100 Subject: [PATCH 1/7] fix: angular native events vs. custom events (#1657) * fix: angular native events vs. custom events * fix: issue with linting * chore: update snapshots * Update .changeset/polite-pugs-pull.md --------- Co-authored-by: Sami Jaber --- .changeset/polite-pugs-pull.md | 31 +++++ .../__snapshots__/angular.import.test.ts.snap | 8 +- .../__snapshots__/angular.mapper.test.ts.snap | 8 +- .../__snapshots__/angular.state.test.ts.snap | 8 +- .../__snapshots__/angular.styles.test.ts.snap | 8 +- .../__snapshots__/angular.test.ts.snap | 16 ++- .../angular/output-event-bindings.raw.tsx | 10 +- .../core/src/generators/alpine/generate.ts | 17 +-- packages/core/src/generators/angular/index.ts | 28 +++-- packages/core/src/generators/angular/types.ts | 15 ++- packages/core/src/generators/helpers/rsc.ts | 3 +- .../core/src/generators/html/generator.ts | 70 +++++------ .../core/src/generators/liquid/generator.ts | 3 +- packages/core/src/generators/lit/generate.ts | 3 +- .../core/src/generators/marko/generate.ts | 3 +- .../core/src/generators/mitosis/generator.ts | 32 ++--- .../qwik/helpers/add-prevent-default.ts | 7 +- .../src/generators/qwik/helpers/handlers.ts | 3 +- .../core/src/generators/qwik/src-generator.ts | 3 +- packages/core/src/generators/react/blocks.ts | 3 +- packages/core/src/generators/solid/blocks.ts | 3 +- .../src/generators/stencil/helpers/index.ts | 3 +- packages/core/src/generators/svelte/blocks.ts | 5 +- .../core/src/generators/swift/generator.ts | 3 +- .../core/src/generators/template/generator.ts | 3 +- packages/core/src/generators/vue/blocks.ts | 5 +- packages/core/src/helpers/event-handlers.ts | 111 +++++++++++++++++- packages/core/src/helpers/is-children.ts | 2 +- 28 files changed, 314 insertions(+), 100 deletions(-) create mode 100644 .changeset/polite-pugs-pull.md diff --git a/.changeset/polite-pugs-pull.md b/.changeset/polite-pugs-pull.md new file mode 100644 index 0000000000..a15e74df56 --- /dev/null +++ b/.changeset/polite-pugs-pull.md @@ -0,0 +1,31 @@ +--- +'@builder.io/mitosis': patch +--- + +[angular]: Fix issue with events forced to become `toLowerCase()`. + +Based on [choosing-event-names](https://angular.dev/guide/components/outputs#choosing-event-names) custom events are camelCase. +[DOM events](https://www.w3schools.com/jsref/dom_obj_event.asp) are always lower-cased for Angular components. + +Checkout [event-handlers.ts](https://github.com/BuilderIO/mitosis/blob/main/packages/core/src/helpers/event-handlers.ts) for a list of all events that are automatically lower-cased. Everything else will be treated as a custom event and therefore camelCased. + +If you need some other event to be lower-cased you can use `useMetadata.angular.nativeEvents`: + +```tsx +import { useMetadata } from '@builder.io/mitosis'; + +useMetadata({ + angular: { + nativeEvents: ['onNativeEvent'], + }, +}); + +export default function MyComponent(props) { + return ( +
+ console.log(event)} /> + Hello! +
+ ); +} +``` diff --git a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap index 6eeb8de867..5587defbd3 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap @@ -5242,7 +5242,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! @@ -13012,7 +13014,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! diff --git a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap index fa0867c783..0fa4c40421 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap @@ -5327,7 +5327,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! @@ -13225,7 +13227,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! diff --git a/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap index 70b083603c..de23dc6e71 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap @@ -5442,7 +5442,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! @@ -13489,7 +13491,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! diff --git a/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap index b00b71c8cf..48f5cc8285 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap @@ -4703,7 +4703,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! @@ -11667,7 +11669,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! diff --git a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap index daccb367f9..7c285bc01d 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap @@ -9868,7 +9868,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! @@ -9906,7 +9908,9 @@ import { CommonModule } from \\"@angular/common\\"; Hello! I can run in React, Vue, Solid, or Liquid! @@ -24494,7 +24498,9 @@ import { Component } from \\"@angular/core\\"; Hello! I can run in React, Vue, Solid, or Liquid! @@ -24532,7 +24538,9 @@ import { CommonModule } from \\"@angular/common\\"; Hello! I can run in React, Vue, Solid, or Liquid! diff --git a/packages/core/src/__tests__/data/angular/output-event-bindings.raw.tsx b/packages/core/src/__tests__/data/angular/output-event-bindings.raw.tsx index d2fc81aa76..34095f04cc 100644 --- a/packages/core/src/__tests__/data/angular/output-event-bindings.raw.tsx +++ b/packages/core/src/__tests__/data/angular/output-event-bindings.raw.tsx @@ -1,4 +1,10 @@ -import { useState } from '@builder.io/mitosis'; +import { useMetadata, useState } from '@builder.io/mitosis'; + +useMetadata({ + angular: { + nativeEvents: ['onFakeNative'], + }, +}); export default function MyComponent(props) { const [name, setName] = useState('Steve'); @@ -9,6 +15,8 @@ export default function MyComponent(props) { value={name} onChange={(event) => setName(event.target.value)} onChangeOrSomething={(event) => setName(event.target.value)} + onFakeNative={(event) => setName(event.target.value)} + onAnimationEnd={(event) => setName(event.target.value)} /> Hello! I can run in React, Vue, Solid, or Liquid! diff --git a/packages/core/src/generators/alpine/generate.ts b/packages/core/src/generators/alpine/generate.ts index f0a55519cb..93d11d9c11 100644 --- a/packages/core/src/generators/alpine/generate.ts +++ b/packages/core/src/generators/alpine/generate.ts @@ -1,6 +1,8 @@ +import { SELF_CLOSING_HTML_TAGS } from '@/constants/html_tags'; import { ToAlpineOptions } from '@/generators/alpine/types'; import { babelTransformCode } from '@/helpers/babel-transform'; import { dashCase } from '@/helpers/dash-case'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { fastClone } from '@/helpers/fast-clone'; import { getRefs } from '@/helpers/get-refs'; import { getStateObjectStringFromComponent } from '@/helpers/get-state-object-string'; @@ -10,18 +12,17 @@ import { replaceIdentifiers } from '@/helpers/replace-identifiers'; import { stripMetaProperties } from '@/helpers/strip-meta-properties'; import { stripStateAndPropsRefs } from '@/helpers/strip-state-and-props-refs'; import { collectCss } from '@/helpers/styles/collect-css'; -import { MitosisComponent } from '@/types/mitosis-component'; -import { checkIsForNode, ForNode, MitosisNode } from '@/types/mitosis-node'; -import { TranspilerGenerator } from '@/types/transpiler'; -import { camelCase, flowRight as compose, curry, flow } from 'lodash'; -import { format } from 'prettier/standalone'; -import { SELF_CLOSING_HTML_TAGS } from '../../constants/html_tags'; import { runPostCodePlugins, runPostJsonPlugins, runPreCodePlugins, runPreJsonPlugins, -} from '../../modules/plugins'; +} from '@/modules/plugins'; +import { MitosisComponent } from '@/types/mitosis-component'; +import { ForNode, MitosisNode, checkIsForNode } from '@/types/mitosis-node'; +import { TranspilerGenerator } from '@/types/transpiler'; +import { camelCase, flowRight as compose, curry, flow } from 'lodash'; +import { format } from 'prettier/standalone'; import { renderMountHook } from './render-mount-hook'; import { hasRootUpdateHook, renderUpdateHooks } from './render-update-hooks'; @@ -167,7 +168,7 @@ const blockToAlpine = (json: MitosisNode | ForNode, options: ToAlpineOptions = { // TODO: proper babel transform to replace. Util for this const useValue = stripStateAndPropsRefs(value); - if (key.startsWith('on')) { + if (checkIsEvent(key)) { str += bindEventHandler(options)(key, value); } else if (key === 'ref') { str += ` x-ref="${useValue}"`; diff --git a/packages/core/src/generators/angular/index.ts b/packages/core/src/generators/angular/index.ts index b31710901d..20bd23ecf9 100644 --- a/packages/core/src/generators/angular/index.ts +++ b/packages/core/src/generators/angular/index.ts @@ -63,6 +63,7 @@ import { ToAngularOptions, } from './types'; +import { checkIsBindingNativeEvent, checkIsEvent } from '@/helpers/event-handlers'; import { parse } from './parse-selector'; const { types } = babel; @@ -226,10 +227,20 @@ const stringifyBinding = const { code, arguments: cusArgs = ['event'] } = binding!; // TODO: proper babel transform to replace. Util for this - if (keyToUse.startsWith('on')) { + if (checkIsEvent(keyToUse)) { const { event, value } = processEventBinding(keyToUse, code, node.name, cusArgs[0]); - // Angular events are all lowerCased - return ` (${event.toLowerCase()})="${value}"`; + + // native events are all lowerCased + const lowerCaseEvent = event.toLowerCase(); + const eventKey = + checkIsBindingNativeEvent(event) || + blockOptions.nativeEvents?.find( + (nativeEvent) => + nativeEvent === keyToUse || nativeEvent === event || nativeEvent === lowerCaseEvent, + ) + ? lowerCaseEvent + : event; + return ` (${eventKey})="${value}"`; } else if (keyToUse === 'class') { return ` [class]="${code}" `; } else if (keyToUse === 'ref' || keyToUse === 'spreadRef') { @@ -281,7 +292,7 @@ const handleNgOutletBindings = (node: MitosisNode, options: ToAngularOptions) => let keyToUse = key.includes('-') ? `'${key}'` : key; keyToUse = keyToUse.replace('state.', '').replace('props.', ''); - if (key.startsWith('on')) { + if (checkIsEvent(key)) { const { event, value } = processEventBinding(key, code, node.name, cusArgs[0]); allProps += `on${event.charAt(0).toUpperCase() + event.slice(1)}: ${value.replace( /\(.*?\)/g, @@ -311,6 +322,7 @@ export const blockToAngular = ({ options = {}, blockOptions = { nativeAttributes: [], + nativeEvents: [], }, }: { root: MitosisComponent; @@ -659,7 +671,7 @@ const handleBindings = ( if (item.name === 'For') continue; if (key === 'key') continue; - if (key.startsWith('on')) { + if (checkIsEvent(key)) { const { arguments: cusArgs = ['event'] } = item.bindings[key]!; const eventBindingName = `${generateNewBindingName(index, item.name)}_event`; if ( @@ -691,7 +703,7 @@ const handleBindings = ( })`; } } else if (item.bindings[key]?.code) { - if (item.bindings[key]?.type !== 'spread' && !key.startsWith('on')) { + if (item.bindings[key]?.type !== 'spread' && !checkIsEvent(key)) { json.state[newBindingName] = { code: 'null', type: 'property' }; makeReactiveState( json, @@ -699,7 +711,7 @@ const handleBindings = ( `this.${newBindingName} = ${item.bindings[key]!.code}`, ); item.bindings[key]!.code = `state.${newBindingName}`; - } else if (key.startsWith('on')) { + } else if (checkIsEvent(key)) { const { arguments: cusArgs = ['event'] } = item.bindings[key]!; if ( item.bindings[key]?.code.trim().startsWith('{') && @@ -941,6 +953,7 @@ export const componentToAngular: TranspilerGenerator = blockOptions: { childComponents, nativeAttributes: useMetadata?.angular?.nativeAttributes ?? [], + nativeEvents: useMetadata?.angular?.nativeEvents ?? [], }, }); if (options.state === 'inline-with-wrappers') { @@ -964,6 +977,7 @@ export const componentToAngular: TranspilerGenerator = { childComponents, nativeAttributes: useMetadata?.angular?.nativeAttributes ?? [], + nativeEvents: useMetadata?.angular?.nativeEvents ?? [], }, ); diff --git a/packages/core/src/generators/angular/types.ts b/packages/core/src/generators/angular/types.ts index ac4ef1cec2..9baa5e67e2 100644 --- a/packages/core/src/generators/angular/types.ts +++ b/packages/core/src/generators/angular/types.ts @@ -26,10 +26,19 @@ export const DEFAULT_ANGULAR_OPTIONS: ToAngularOptions = { }; export type AngularMetadata = { - /* Mitosis uses `attr.XXX` as default see https://angular.io/guide/attribute-binding. - If you want to skip some you can use the 'nativeAttributes'. */ + /** + * Mitosis uses `attr.XXX` as default see https://angular.io/guide/attribute-binding. + * If you want to skip some you can use the 'nativeAttributes'. + */ nativeAttributes?: string[]; - /* Overwrite default selector for component. Default will be kebab case (MyComponent -> my-component) */ + /** + * If you encounter some native events which aren't generated in lower-case. + * Create a new PR inside [event-handlers.ts](https://github.com/BuilderIO/mitosis/blob/main/packages/core/src/helpers/event-handlers.ts) to fix it for all. + */ + nativeEvents?: string[]; + /** + * Overwrite default selector for component. Default will be kebab case (MyComponent -> my-component) + */ selector?: string; }; diff --git a/packages/core/src/generators/helpers/rsc.ts b/packages/core/src/generators/helpers/rsc.ts index 0b25b4f07c..a88dd8a7bb 100644 --- a/packages/core/src/generators/helpers/rsc.ts +++ b/packages/core/src/generators/helpers/rsc.ts @@ -1,3 +1,4 @@ +import { checkIsEvent } from '@/helpers/event-handlers'; import { isMitosisNode } from '@/helpers/is-mitosis-node'; import type { MitosisComponent } from '@/types/mitosis-component'; import type { MitosisNode } from '@/types/mitosis-node'; @@ -18,7 +19,7 @@ export const checkIfIsClientComponent = (json: MitosisComponent) => { let foundEventListener = false; traverse(json).forEach(function (node) { if (isMitosisNode(node) && !checkIsNodeAMitosisComponent(node)) { - if (Object.keys(node.bindings).filter((item) => item.startsWith('on')).length) { + if (Object.keys(node.bindings).filter((item) => checkIsEvent(item)).length) { foundEventListener = true; this.stop(); } diff --git a/packages/core/src/generators/html/generator.ts b/packages/core/src/generators/html/generator.ts index a23ca9ed25..911d4f42cf 100644 --- a/packages/core/src/generators/html/generator.ts +++ b/packages/core/src/generators/html/generator.ts @@ -1,48 +1,50 @@ +import { SELF_CLOSING_HTML_TAGS } from '@/constants/html_tags'; import { ToHtmlOptions } from '@/generators/html/types'; -import { NodePath, types } from '@babel/core'; -import { pipe } from 'fp-ts/lib/function'; -import { camelCase, kebabCase } from 'lodash'; -import traverse from 'neotraverse/legacy'; -import { format } from 'prettier/standalone'; -import { SELF_CLOSING_HTML_TAGS } from '../../constants/html_tags'; -import { babelTransformExpression } from '../../helpers/babel-transform'; -import { dashCase } from '../../helpers/dash-case'; -import { fastClone } from '../../helpers/fast-clone'; -import { getPropFunctions } from '../../helpers/get-prop-functions'; -import { getProps } from '../../helpers/get-props'; -import { getPropsRef } from '../../helpers/get-props-ref'; -import { getRefs } from '../../helpers/get-refs'; -import { getStateObjectStringFromComponent } from '../../helpers/get-state-object-string'; -import { hasBindingsText } from '../../helpers/has-bindings-text'; -import { hasComponent } from '../../helpers/has-component'; -import { hasProps } from '../../helpers/has-props'; -import { hasStatefulDom } from '../../helpers/has-stateful-dom'; -import isChildren from '../../helpers/is-children'; -import { isHtmlAttribute } from '../../helpers/is-html-attribute'; -import { isMitosisNode } from '../../helpers/is-mitosis-node'; -import { mapRefs } from '../../helpers/map-refs'; -import { initializeOptions } from '../../helpers/merge-options'; -import { getForArguments } from '../../helpers/nodes/for'; -import { removeSurroundingBlock } from '../../helpers/remove-surrounding-block'; -import { renderPreComponent } from '../../helpers/render-imports'; -import { stripMetaProperties } from '../../helpers/strip-meta-properties'; +import { babelTransformExpression } from '@/helpers/babel-transform'; +import { dashCase } from '@/helpers/dash-case'; +import { checkIsEvent } from '@/helpers/event-handlers'; +import { fastClone } from '@/helpers/fast-clone'; +import { getPropFunctions } from '@/helpers/get-prop-functions'; +import { getProps } from '@/helpers/get-props'; +import { getPropsRef } from '@/helpers/get-props-ref'; +import { getRefs } from '@/helpers/get-refs'; +import { getStateObjectStringFromComponent } from '@/helpers/get-state-object-string'; +import { hasBindingsText } from '@/helpers/has-bindings-text'; +import { hasComponent } from '@/helpers/has-component'; +import { hasProps } from '@/helpers/has-props'; +import { hasStatefulDom } from '@/helpers/has-stateful-dom'; +import { isHtmlAttribute } from '@/helpers/is-html-attribute'; +import { isMitosisNode } from '@/helpers/is-mitosis-node'; +import { mapRefs } from '@/helpers/map-refs'; +import { initializeOptions } from '@/helpers/merge-options'; +import { getForArguments } from '@/helpers/nodes/for'; +import { removeSurroundingBlock } from '@/helpers/remove-surrounding-block'; +import { renderPreComponent } from '@/helpers/render-imports'; +import { stripMetaProperties } from '@/helpers/strip-meta-properties'; import { DO_NOT_USE_ARGS, DO_NOT_USE_CONTEXT_VARS_TRANSFORMS, DO_NOT_USE_VARS_TRANSFORMS, StripStateAndPropsRefsOptions, stripStateAndPropsRefs, -} from '../../helpers/strip-state-and-props-refs'; -import { collectCss } from '../../helpers/styles/collect-css'; +} from '@/helpers/strip-state-and-props-refs'; +import { collectCss } from '@/helpers/styles/collect-css'; import { runPostCodePlugins, runPostJsonPlugins, runPreCodePlugins, runPreJsonPlugins, -} from '../../modules/plugins'; -import { MitosisComponent } from '../../types/mitosis-component'; -import { MitosisNode, checkIsForNode } from '../../types/mitosis-node'; -import { TranspilerGenerator } from '../../types/transpiler'; +} from '@/modules/plugins'; +import { MitosisComponent } from '@/types/mitosis-component'; +import { MitosisNode, checkIsForNode } from '@/types/mitosis-node'; +import { TranspilerGenerator } from '@/types/transpiler'; +import { NodePath, types } from '@babel/core'; +import { pipe } from 'fp-ts/lib/function'; +import { camelCase, kebabCase } from 'lodash'; +import traverse from 'neotraverse/legacy'; + +import isChildren from '@/helpers/is-children'; +import { format } from 'prettier/standalone'; import { stringifySingleScopeOnMount } from '../helpers/on-mount'; type ScopeVars = Array; @@ -424,7 +426,7 @@ const blockToHtml = ( // TODO: proper babel transform to replace. Util for this const useValue = value; - if (key.startsWith('on')) { + if (checkIsEvent(key)) { let event = key.replace('on', '').toLowerCase(); const fnName = camelCase(`on-${elId}-${event}`); const codeContent: string = removeSurroundingBlock( diff --git a/packages/core/src/generators/liquid/generator.ts b/packages/core/src/generators/liquid/generator.ts index a2392e7ebf..bf9a43a0b2 100644 --- a/packages/core/src/generators/liquid/generator.ts +++ b/packages/core/src/generators/liquid/generator.ts @@ -1,4 +1,5 @@ import { ToLiquidOptions } from '@/generators/liquid/types'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { format } from 'prettier/standalone'; import { SELF_CLOSING_HTML_TAGS } from '../../constants/html_tags'; import { fastClone } from '../../helpers/fast-clone'; @@ -113,7 +114,7 @@ const blockToLiquid = (json: MitosisNode, options: ToLiquidOptions = {}): string // TODO: proper babel transform to replace. Util for this const useValue = stripStateAndPropsRefs(value); - if (key.startsWith('on')) { + if (checkIsEvent(key)) { // Do nothing } else if (isValidLiquidBinding(useValue)) { str += ` ${key}="{{${useValue}}}" `; diff --git a/packages/core/src/generators/lit/generate.ts b/packages/core/src/generators/lit/generate.ts index a61b5be276..ace3cab4eb 100644 --- a/packages/core/src/generators/lit/generate.ts +++ b/packages/core/src/generators/lit/generate.ts @@ -1,6 +1,7 @@ import { ToLitOptions } from '@/generators/lit/types'; import { dashCase } from '@/helpers/dash-case'; import { dedent } from '@/helpers/dedent'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { fastClone } from '@/helpers/fast-clone'; import { filterEmptyTextNodes } from '@/helpers/filter-empty-text-nodes'; import { getProps } from '@/helpers/get-props'; @@ -92,7 +93,7 @@ const blockToLit = (json: MitosisNode, options: ToLitOptions = {}): string => { // TODO: maybe use ref directive instead // https://lit.dev/docs/templates/directives/#ref str += ` ref="${code}" `; - } else if (key.startsWith('on')) { + } else if (checkIsEvent(key)) { const asyncKeyword = json.bindings[key]?.async ? 'async ' : ''; const useKey = '@' + key.substring(2).toLowerCase(); diff --git a/packages/core/src/generators/marko/generate.ts b/packages/core/src/generators/marko/generate.ts index 257ac43b73..edd79ab8d8 100644 --- a/packages/core/src/generators/marko/generate.ts +++ b/packages/core/src/generators/marko/generate.ts @@ -2,6 +2,7 @@ import { SELF_CLOSING_HTML_TAGS } from '@/constants/html_tags'; import { ToMarkoOptions } from '@/generators/marko/types'; import { dashCase } from '@/helpers/dash-case'; import { dedent } from '@/helpers/dedent'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { fastClone } from '@/helpers/fast-clone'; import { filterEmptyTextNodes } from '@/helpers/filter-empty-text-nodes'; import { getRefs } from '@/helpers/get-refs'; @@ -90,7 +91,7 @@ const blockToMarko = (json: MitosisNode, options: InternalToMarkoOptions): strin str += ` ...(${code}) `; } else if (key === 'ref') { str += ` key="${camelCase(code)}" `; - } else if (key.startsWith('on')) { + } else if (checkIsEvent(key)) { const asyncKeyword = async ? 'async ' : ''; const useKey = key === 'onChange' && json.name === 'input' ? 'onInput' : key; str += ` ${dashCase(useKey)}=(${asyncKeyword}(${cusArgs.join(',')}) => ${processBinding( diff --git a/packages/core/src/generators/mitosis/generator.ts b/packages/core/src/generators/mitosis/generator.ts index 6dc1770eb5..98998f4f06 100644 --- a/packages/core/src/generators/mitosis/generator.ts +++ b/packages/core/src/generators/mitosis/generator.ts @@ -1,27 +1,29 @@ +import { HOOKS } from '@/constants/hooks'; +import { SELF_CLOSING_HTML_TAGS } from '@/constants/html_tags'; import { ToMitosisOptions } from '@/generators/mitosis/types'; +import { dedent } from '@/helpers/dedent'; +import { checkIsEvent } from '@/helpers/event-handlers'; +import { fastClone } from '@/helpers/fast-clone'; +import { getComponents } from '@/helpers/get-components'; +import { getRefs } from '@/helpers/get-refs'; +import { getStateObjectStringFromComponent } from '@/helpers/get-state-object-string'; import { isMitosisNode } from '@/helpers/is-mitosis-node'; +import { isRootTextNode } from '@/helpers/is-root-text-node'; +import { mapRefs } from '@/helpers/map-refs'; +import { renderPreComponent } from '@/helpers/render-imports'; +import { checkHasState } from '@/helpers/state'; import { runPostCodePlugins, runPostJsonPlugins, runPreCodePlugins, runPreJsonPlugins, } from '@/modules/plugins'; +import { MitosisComponent } from '@/types/mitosis-component'; +import { MitosisNode, checkIsForNode, checkIsShowNode } from '@/types/mitosis-node'; +import { TranspilerGenerator } from '@/types/transpiler'; import json5 from 'json5'; import { format } from 'prettier/standalone'; -import { HOOKS } from '../../constants/hooks'; -import { SELF_CLOSING_HTML_TAGS } from '../../constants/html_tags'; -import { dedent } from '../../helpers/dedent'; -import { fastClone } from '../../helpers/fast-clone'; -import { getComponents } from '../../helpers/get-components'; -import { getRefs } from '../../helpers/get-refs'; -import { getStateObjectStringFromComponent } from '../../helpers/get-state-object-string'; -import { isRootTextNode } from '../../helpers/is-root-text-node'; -import { mapRefs } from '../../helpers/map-refs'; -import { renderPreComponent } from '../../helpers/render-imports'; -import { checkHasState } from '../../helpers/state'; -import { MitosisComponent } from '../../types/mitosis-component'; -import { MitosisNode, checkIsForNode, checkIsShowNode } from '../../types/mitosis-node'; -import { TranspilerGenerator } from '../../types/transpiler'; + import { blockToReact, componentToReact } from '../react'; export const DEFAULT_FORMAT: ToMitosisOptions['format'] = 'legacy'; @@ -144,7 +146,7 @@ export const blockToMitosis = ( if (json.bindings[key]?.type === 'spread') { str += ` {...(${json.bindings[key]?.code})} `; - } else if (key.startsWith('on')) { + } else if (checkIsEvent(key)) { const { arguments: cusArgs = ['event'], async } = json.bindings[key]!; const asyncKeyword = async ? 'async ' : ''; str += ` ${key}={${asyncKeyword}(${cusArgs.join(',')}) => ${value.replace(/\s*;$/, '')}} `; diff --git a/packages/core/src/generators/qwik/helpers/add-prevent-default.ts b/packages/core/src/generators/qwik/helpers/add-prevent-default.ts index 72776ca000..1592b9c757 100644 --- a/packages/core/src/generators/qwik/helpers/add-prevent-default.ts +++ b/packages/core/src/generators/qwik/helpers/add-prevent-default.ts @@ -1,6 +1,7 @@ +import { checkIsEvent } from '@/helpers/event-handlers'; +import { isMitosisNode } from '@/helpers/is-mitosis-node'; +import { MitosisComponent } from '@/types/mitosis-component'; import traverse from 'neotraverse/legacy'; -import { isMitosisNode } from '../../../helpers/is-mitosis-node'; -import { MitosisComponent } from '../../../types/mitosis-component'; /** * Find event handlers that explicitly call .preventDefault() and @@ -12,7 +13,7 @@ export function addPreventDefault(json: MitosisComponent) { if (isMitosisNode(node)) { if (node.bindings) { for (const key of Object.keys(node.bindings)) { - if (key.startsWith('on')) { + if (checkIsEvent(key)) { if (node.bindings[key]?.code.includes('.preventDefault()')) { const event = key.slice(2).toLowerCase(); node.properties['preventdefault:' + event] = ''; diff --git a/packages/core/src/generators/qwik/helpers/handlers.ts b/packages/core/src/generators/qwik/helpers/handlers.ts index 24abda603d..a4fdcfddd2 100644 --- a/packages/core/src/generators/qwik/helpers/handlers.ts +++ b/packages/core/src/generators/qwik/helpers/handlers.ts @@ -1,3 +1,4 @@ +import { checkIsEvent } from '@/helpers/event-handlers'; import { MitosisNode } from '../../../types/mitosis-node'; import { renderUseLexicalScope } from '../component'; import { arrowFnBlock, EmitFn, File, SrcBuilder } from '../src-generator'; @@ -61,5 +62,5 @@ function renderHandler(file: File, symbol: string, code: string) { } function isEventName(name: string) { - return name.startsWith('on') && name.charAt(2).toUpperCase() == name.charAt(2); + return checkIsEvent(name) && name.charAt(2).toUpperCase() == name.charAt(2); } diff --git a/packages/core/src/generators/qwik/src-generator.ts b/packages/core/src/generators/qwik/src-generator.ts index 5db00c84c0..abbf04ddd5 100644 --- a/packages/core/src/generators/qwik/src-generator.ts +++ b/packages/core/src/generators/qwik/src-generator.ts @@ -1,6 +1,7 @@ import parserTypeScript from 'prettier/parser-typescript'; import { format } from 'prettier/standalone'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { SELF_CLOSING_HTML_TAGS } from '../../constants/html_tags'; import { convertExportDefaultToReturn } from '../../parsers/builder'; import { stableJSONserialize } from './helpers/stable-serialize'; @@ -424,7 +425,7 @@ export class SrcBuilder { } function isEvent(name: string): boolean { - return name.startsWith('on') && isUppercase(name.charAt(2)) && !name.endsWith('$'); + return checkIsEvent(name) && isUppercase(name.charAt(2)) && !name.endsWith('$'); } function isUppercase(ch: string): boolean { diff --git a/packages/core/src/generators/react/blocks.ts b/packages/core/src/generators/react/blocks.ts index 3d7fc3736e..40dc24b97d 100644 --- a/packages/core/src/generators/react/blocks.ts +++ b/packages/core/src/generators/react/blocks.ts @@ -1,3 +1,4 @@ +import { checkIsEvent } from '@/helpers/event-handlers'; import { filterEmptyTextNodes } from '@/helpers/filter-empty-text-nodes'; import isChildren from '@/helpers/is-children'; import { isRootTextNode } from '@/helpers/is-root-text-node'; @@ -296,7 +297,7 @@ export const blockToReact = ( } if (json.bindings[key]?.type === 'spread') { str += ` {...(${value})} `; - } else if (key.startsWith('on')) { + } else if (checkIsEvent(key)) { const asyncKeyword = json.bindings[key]?.async ? 'async ' : ''; const { arguments: cusArgs = ['event'] } = json.bindings[key]!; const eventName = options.type === 'native' ? NATIVE_EVENT_MAPPER[key] || key : key; diff --git a/packages/core/src/generators/solid/blocks.ts b/packages/core/src/generators/solid/blocks.ts index 3f6e2f0039..8f3b57741d 100644 --- a/packages/core/src/generators/solid/blocks.ts +++ b/packages/core/src/generators/solid/blocks.ts @@ -1,4 +1,5 @@ import { babelTransformExpression } from '@/helpers/babel-transform'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { filterEmptyTextNodes } from '@/helpers/filter-empty-text-nodes'; import { isMitosisNode } from '@/helpers/is-mitosis-node'; import { objectHasKey } from '@/helpers/typescript'; @@ -89,7 +90,7 @@ export const blockToSolid = ( if (type === 'spread') { str += ` {...(${code})} `; - } else if (key.startsWith('on')) { + } else if (checkIsEvent(key)) { const useKey = key === 'onChange' && json.name === 'input' ? 'onInput' : key; const asyncKeyword = json.bindings[key]?.async ? 'async ' : ''; str += ` ${useKey}={${asyncKeyword}(${cusArg.join(',')}) => ${code}} `; diff --git a/packages/core/src/generators/stencil/helpers/index.ts b/packages/core/src/generators/stencil/helpers/index.ts index 61c5bb06bd..f4dd441239 100644 --- a/packages/core/src/generators/stencil/helpers/index.ts +++ b/packages/core/src/generators/stencil/helpers/index.ts @@ -1,11 +1,12 @@ import { ToStencilOptions } from '@/generators/stencil/types'; import { dashCase } from '@/helpers/dash-case'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { renderPreComponent } from '@/helpers/render-imports'; import { stripStateAndPropsRefs } from '@/helpers/strip-state-and-props-refs'; import { MitosisComponent, MitosisState } from '@/types/mitosis-component'; import { MitosisNode } from '@/types/mitosis-node'; -export const isEvent = (key: string): boolean => key.startsWith('on'); +export const isEvent = (key: string): boolean => checkIsEvent(key); /** * We need to "emit" events those can be on multiple places, so we do it as post step diff --git a/packages/core/src/generators/svelte/blocks.ts b/packages/core/src/generators/svelte/blocks.ts index ae492cfbe1..7fe2388256 100644 --- a/packages/core/src/generators/svelte/blocks.ts +++ b/packages/core/src/generators/svelte/blocks.ts @@ -1,4 +1,5 @@ import { createSingleBinding } from '@/helpers/bindings'; +import { checkIsEvent } from '@/helpers/event-handlers'; import isChildren from '@/helpers/is-children'; import { isUpperCase } from '@/helpers/is-upper-case'; import { getForArguments } from '@/helpers/nodes/for'; @@ -222,7 +223,7 @@ const stringifyBinding = if (type === 'spread') { const spreadValue = key === 'props' ? '$$props' : code; return ` {...${spreadValue}} `; - } else if (key.startsWith('on') && isValidHtmlTag) { + } else if (checkIsEvent(key) && isValidHtmlTag) { const { async } = binding; // handle html native on[event] props const event = key.replace('on', '').toLowerCase(); @@ -236,7 +237,7 @@ const stringifyBinding = const asyncKeyword = async ? 'async ' : ''; return ` on:${event}="{${asyncKeyword}(${cusArgs.join(',')}) => {${valueWithoutBlock}}}" `; } - } else if (key.startsWith('on')) { + } else if (checkIsEvent(key)) { // handle on[custom event] props const valueWithoutBlock = removeSurroundingBlock(code); diff --git a/packages/core/src/generators/swift/generator.ts b/packages/core/src/generators/swift/generator.ts index 5e9370c853..af7a87ee47 100644 --- a/packages/core/src/generators/swift/generator.ts +++ b/packages/core/src/generators/swift/generator.ts @@ -1,4 +1,5 @@ import { ToSwiftOptions } from '@/generators/swift/types'; +import { checkIsEvent } from '@/helpers/event-handlers'; import traverse from 'neotraverse/legacy'; import { dedent } from '../../helpers/dedent'; import { fastClone } from '../../helpers/fast-clone'; @@ -149,7 +150,7 @@ const blockToSwift = (json: MitosisNode, options: ToSwiftOptions): string => { continue; } - if (key.startsWith('on')) { + if (checkIsEvent(key)) { if (key === 'onClick') { continue; } else { diff --git a/packages/core/src/generators/template/generator.ts b/packages/core/src/generators/template/generator.ts index 9c8325d4e1..4877477662 100644 --- a/packages/core/src/generators/template/generator.ts +++ b/packages/core/src/generators/template/generator.ts @@ -1,4 +1,5 @@ import { ToTemplateOptions } from '@/generators/template/types'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { format } from 'prettier/standalone'; import { SELF_CLOSING_HTML_TAGS } from '../../constants/html_tags'; import { dedent } from '../../helpers/dedent'; @@ -76,7 +77,7 @@ const blockToTemplate = (json: MitosisNode, options: ToTemplateOptions = {}) => // TODO: proper babel transform to replace. Util for this const useValue = value; - if (key.startsWith('on')) { + if (checkIsEvent(key)) { // Do nothing } else { str += ` ${key}="\${${useValue}}" `; diff --git a/packages/core/src/generators/vue/blocks.ts b/packages/core/src/generators/vue/blocks.ts index 639e7854f1..0f6f7e89fa 100644 --- a/packages/core/src/generators/vue/blocks.ts +++ b/packages/core/src/generators/vue/blocks.ts @@ -1,4 +1,5 @@ import { createSingleBinding } from '@/helpers/bindings'; +import { checkIsEvent } from '@/helpers/event-handlers'; import { filterEmptyTextNodes } from '@/helpers/filter-empty-text-nodes'; import isChildren from '@/helpers/is-children'; import { isMitosisNode } from '@/helpers/is-mitosis-node'; @@ -130,7 +131,7 @@ const stringifyBinding = // TODO: proper babel transform to replace. Util for this const useValue = value?.code || ''; - if (key.startsWith('on') && isValidHtmlTag) { + if (checkIsEvent(key) && isValidHtmlTag) { // handle html native on[event] props const { arguments: cusArgs = ['event'], async } = value; let event = key.replace('on', '').toLowerCase(); @@ -154,7 +155,7 @@ const stringifyBinding = const eventHandlerKey = `${SPECIAL_PROPERTIES.V_ON_AT}${event}`; return `${eventHandlerKey}="${eventHandlerValue}"`; - } else if (key.startsWith('on')) { + } else if (checkIsEvent(key)) { // handle on[custom event] props const { arguments: cusArgs = ['event'] } = node.bindings[key]!; return `:${key}="(${cusArgs.join(',')}) => ${encodeQuotes(useValue)}"`; diff --git a/packages/core/src/helpers/event-handlers.ts b/packages/core/src/helpers/event-handlers.ts index d263630434..0f938db322 100644 --- a/packages/core/src/helpers/event-handlers.ts +++ b/packages/core/src/helpers/event-handlers.ts @@ -1 +1,110 @@ -export const checkIsBindingEventHandler = (code: string) => code.startsWith('on'); +export const checkIsEvent = (code: string) => code.startsWith('on'); + +const nativeEvents = [ + 'abort', + 'animationcancel', + 'animationend', + 'animationiteration', + 'animationstart', + 'auxclick', + 'beforeinput', + 'beforetoggle', + 'blur', + 'cancel', + 'canplay', + 'canplaythrough', + 'change', + 'click', + 'close', + 'compositionend', + 'compositionstart', + 'compositionupdate', + 'contextlost', + 'contextmenu', + 'contextrestored', + 'copy', + 'cuechange', + 'cut', + 'dblclick', + 'drag', + 'dragend', + 'dragenter', + 'dragleave', + 'dragover', + 'dragstart', + 'drop', + 'durationchange', + 'emptied', + 'ended', + 'error', + 'focus', + 'focusin', + 'focusout', + 'formdata', + 'gotpointercapture', + 'input', + 'invalid', + 'keydown', + 'keypress', + 'keyup', + 'load', + 'loadeddata', + 'loadedmetadata', + 'loadstart', + 'lostpointercapture', + 'mousedown', + 'mouseenter', + 'mouseleave', + 'mousemove', + 'mouseout', + 'mouseover', + 'mouseup', + 'paste', + 'pause', + 'play', + 'playing', + 'pointercancel', + 'pointerdown', + 'pointerenter', + 'pointerleave', + 'pointermove', + 'pointerout', + 'pointerover', + 'pointerup', + 'progress', + 'ratechange', + 'reset', + 'resize', + 'scroll', + 'scrollend', + 'securitypolicyviolation', + 'seeked', + 'seeking', + 'select', + 'selectionchange', + 'selectstart', + 'slotchange', + 'stalled', + 'submit', + 'suspend', + 'timeupdate', + 'toggle', + 'touchcancel', + 'touchend', + 'touchmove', + 'touchstart', + 'transitioncancel', + 'transitionend', + 'transitionrun', + 'transitionstart', + 'volumechange', + 'waiting', + 'webkitanimationend', + 'webkitanimationiteration', + 'webkitanimationstart', + 'webkittransitionend', + 'wheel', +]; + +export const checkIsBindingNativeEvent = (code: string) => + !!nativeEvents.find((nativeEvent) => nativeEvent === code.toLowerCase()); diff --git a/packages/core/src/helpers/is-children.ts b/packages/core/src/helpers/is-children.ts index acbceac1cd..7c7ef76a8b 100644 --- a/packages/core/src/helpers/is-children.ts +++ b/packages/core/src/helpers/is-children.ts @@ -1,4 +1,4 @@ -import { MitosisNode } from '../types/mitosis-node'; +import { MitosisNode } from '@/types/mitosis-node'; export const getTextValue = (node: MitosisNode) => { const textValue = node.bindings._text?.code || node.properties.__text || ''; From af43f50798611b6c75bf94bd8ec855171471eb12 Mon Sep 17 00:00:00 2001 From: Nicolas Merget <104347736+nmerget@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:51:59 +0100 Subject: [PATCH 2/7] Feat complex metadata (#1638) * feat: improve parseJSX to resolve complex useMetadata * fix: issue with metadata always be flat without correct depth * chore: add changeset * chore: add example for complex useMetadata * chore: run fmt * fix: complex metadata with spread variable * chore: run fmt * chore: update snapshots * chore: moved `isTypescriptFile` from `src/helpers` to `parsers/jsx/helpers` * chore: update snapshots --- .changeset/clean-cobras-know.md | 31 + examples/metdata/.eslintrc.js | 18 + examples/metdata/.gitignore | 1 + examples/metdata/README.md | 3 + examples/metdata/mitosis.config.js | 37 + examples/metdata/package.json | 22 + examples/metdata/src/components/data.ts | 13 + .../metdata/src/components/metadata.lite.tsx | 8 + examples/metdata/src/shared/data.ts | 11 + examples/metdata/src/shared/model.ts | 5 + examples/metdata/tsconfig.json | 10 + .../__snapshots__/alpine.test.ts.snap | 104 ++- .../__snapshots__/angular.import.test.ts.snap | 236 ++++- .../__snapshots__/angular.mapper.test.ts.snap | 240 ++++- .../__snapshots__/angular.state.test.ts.snap | 236 ++++- .../__snapshots__/angular.styles.test.ts.snap | 208 ++++- .../__snapshots__/angular.test.ts.snap | 444 ++++++++- .../__tests__/__snapshots__/html.test.ts.snap | 190 +++- .../__snapshots__/liquid.test.ts.snap | 82 +- .../__tests__/__snapshots__/lit.test.ts.snap | 158 +++- .../__snapshots__/marko.test.ts.snap | 94 +- .../__snapshots__/mitosis.test.ts.snap | 474 +++++++++- .../__snapshots__/parse-jsx.test.ts.snap | 349 +++++++ .../__snapshots__/preact.test.ts.snap | 114 ++- .../__tests__/__snapshots__/qwik.test.ts.snap | 118 ++- .../__snapshots__/react-native.test.ts.snap | 162 +++- .../react-state-builder.test.ts.snap | 118 ++- .../react-state-mobx.test.ts.snap | 114 ++- .../react-state-solid.test.ts.snap | 110 ++- .../react-state-valtio.test.ts.snap | 110 ++- .../react-state-variables.test.ts.snap | 110 ++- .../__snapshots__/react.test.ts.snap | 110 ++- .../__tests__/__snapshots__/rsc.test.ts.snap | 880 +++++++++++++++--- .../__snapshots__/solid.test.ts.snap | 228 ++++- .../__snapshots__/stencil.test.ts.snap | 134 ++- .../__snapshots__/svelte.test.ts.snap | 379 +++++++- .../__tests__/__snapshots__/taro.test.ts.snap | 114 ++- .../vue-composition.test.ts.snap | 106 ++- .../__tests__/__snapshots__/vue.test.ts.snap | 122 ++- .../__snapshots__/webcomponent.test.ts.snap | 470 +++++++++- .../core/src/__tests__/data/meta/figma.ts | 12 + .../src/__tests__/data/meta/figma/data.ts | 48 + .../__tests__/data/meta/figma/figma.raw.tsx | 19 + packages/core/src/__tests__/data/meta/meta.ts | 1 + .../data/meta/sub/complex-meta.raw.tsx | 11 + .../src/__tests__/data/meta/sub/meta-model.ts | 7 + .../src/__tests__/data/meta/sub/meta-sub.ts | 14 + packages/core/src/__tests__/react.test.ts | 2 +- packages/core/src/__tests__/test-generator.ts | 41 +- packages/core/src/parsers/jsx/helpers.ts | 37 +- packages/core/src/parsers/jsx/hooks/index.ts | 45 +- .../src/parsers/jsx/hooks/use-metadata.ts | 219 +++++ packages/core/src/parsers/jsx/imports.ts | 15 +- packages/core/src/parsers/jsx/jsx.ts | 243 +++-- packages/core/src/parsers/jsx/types.ts | 9 +- .../src/routes/docs/customizability/index.mdx | 14 +- yarn.lock | 10 + 57 files changed, 6713 insertions(+), 507 deletions(-) create mode 100644 .changeset/clean-cobras-know.md create mode 100644 examples/metdata/.eslintrc.js create mode 100644 examples/metdata/.gitignore create mode 100644 examples/metdata/README.md create mode 100644 examples/metdata/mitosis.config.js create mode 100644 examples/metdata/package.json create mode 100644 examples/metdata/src/components/data.ts create mode 100644 examples/metdata/src/components/metadata.lite.tsx create mode 100644 examples/metdata/src/shared/data.ts create mode 100644 examples/metdata/src/shared/model.ts create mode 100644 examples/metdata/tsconfig.json create mode 100644 packages/core/src/__tests__/data/meta/figma.ts create mode 100644 packages/core/src/__tests__/data/meta/figma/data.ts create mode 100644 packages/core/src/__tests__/data/meta/figma/figma.raw.tsx create mode 100644 packages/core/src/__tests__/data/meta/meta.ts create mode 100644 packages/core/src/__tests__/data/meta/sub/complex-meta.raw.tsx create mode 100644 packages/core/src/__tests__/data/meta/sub/meta-model.ts create mode 100644 packages/core/src/__tests__/data/meta/sub/meta-sub.ts create mode 100644 packages/core/src/parsers/jsx/hooks/use-metadata.ts diff --git a/.changeset/clean-cobras-know.md b/.changeset/clean-cobras-know.md new file mode 100644 index 0000000000..7e55cccc2e --- /dev/null +++ b/.changeset/clean-cobras-know.md @@ -0,0 +1,31 @@ +--- +'@builder.io/mitosis': patch +--- + +[All] Refactored `useMetadata` hook to enable import resolution instead of simple `JSON5` parsing. + +You could use a normal JS `Object` and import it inside your `*.lite.tsx` file like this: + +```ts +// data.ts + +export const myMetadata: Record = { + a: 'b', + c: 1, +}; +``` + +```tsx +// my-button.lite.tsx +import { useMetadata } from '@builder.io/mitosis'; +import { myMetadata } from './data.ts'; + +useMetadata({ + x: 'y', + my: myMetadata, +}); + +export default function MyButton() { + return ; +} +``` diff --git a/examples/metdata/.eslintrc.js b/examples/metdata/.eslintrc.js new file mode 100644 index 0000000000..6251926add --- /dev/null +++ b/examples/metdata/.eslintrc.js @@ -0,0 +1,18 @@ +module.exports = { + env: { + browser: true, + }, + plugins: ["@builder.io/mitosis"], + parser: "@typescript-eslint/parser", + extends: [], + parserOptions: { + ecmaVersion: 2018, + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + rules: { + "@builder.io/mitosis/no-conditional-render": "warn", + }, +}; diff --git a/examples/metdata/.gitignore b/examples/metdata/.gitignore new file mode 100644 index 0000000000..6caf68aff4 --- /dev/null +++ b/examples/metdata/.gitignore @@ -0,0 +1 @@ +output \ No newline at end of file diff --git a/examples/metdata/README.md b/examples/metdata/README.md new file mode 100644 index 0000000000..9e598a89e6 --- /dev/null +++ b/examples/metdata/README.md @@ -0,0 +1,3 @@ +# Metadata example for Mitosis + +This is an example to showcase the ``useMetadata`` hook. You can use this to set predefined configuration parameters for each component. Or you can add additional parameters to use them in a plugin. diff --git a/examples/metdata/mitosis.config.js b/examples/metdata/mitosis.config.js new file mode 100644 index 0000000000..217056e20c --- /dev/null +++ b/examples/metdata/mitosis.config.js @@ -0,0 +1,37 @@ +const metadataPlugin = () => ({ + code: { + pre: (code, json) => { + if (json.meta.useMetadata) { + return ` + /** + useMetadata: + ${JSON.stringify(json.meta.useMetadata)} + */ + + ${code}`; + } + + return code; + }, + }, +}); + +module.exports = { + files: 'src/**', + commonOptions: { + plugins: [metadataPlugin], + }, + targets: [ + 'react', + // still unsupported + // 'qwik', + // 'builder', + 'vue', + 'html', + // TO-DO: fix error causing svelte output not to work + // 'svelte', + 'solid', + 'angular', + 'webcomponent', + ], +}; diff --git a/examples/metdata/package.json b/examples/metdata/package.json new file mode 100644 index 0000000000..64e6eb4d19 --- /dev/null +++ b/examples/metdata/package.json @@ -0,0 +1,22 @@ +{ + "name": "@builder.io/metadata-example", + "private": true, + "scripts": { + "build": "mitosis build", + "lint": "eslint" + }, + "exports": { + "./react/*": "./dist/react/src/*", + "./qwik/*": "./dist/qwik/src/*", + "./vue/*": "./dist/vue/src/*", + "./svelte/*": "./dist/svelte/src/*", + "./angular/*": "./dist/angular/src/*", + "./html/*": "./dist/html/src/*", + "./solid/*": "./dist/solid/src/*" + }, + "dependencies": { + "@builder.io/mitosis": "workspace:*", + "@builder.io/mitosis-cli": "workspace:*", + "eslint": "^7.21.0" + } +} diff --git a/examples/metdata/src/components/data.ts b/examples/metdata/src/components/data.ts new file mode 100644 index 0000000000..a363ffeec9 --- /dev/null +++ b/examples/metdata/src/components/data.ts @@ -0,0 +1,13 @@ +import { ComponentMetadata } from '@builder.io/mitosis'; +import { customMetaData } from '../shared/data'; + +export const metadata: ComponentMetadata = { + regularKey: 'abc', + 'some-key': customMetaData, + react: { + forwardRef: 'xxx', + }, + vue: { + customKey: 'yyy', + }, +}; diff --git a/examples/metdata/src/components/metadata.lite.tsx b/examples/metdata/src/components/metadata.lite.tsx new file mode 100644 index 0000000000..a143f9a0b1 --- /dev/null +++ b/examples/metdata/src/components/metadata.lite.tsx @@ -0,0 +1,8 @@ +import { useMetadata } from '@builder.io/mitosis'; +import { metadata } from './data'; + +useMetadata({ ...metadata }); + +export default function MetadataExample() { + return
Metadata
; +} diff --git a/examples/metdata/src/shared/data.ts b/examples/metdata/src/shared/data.ts new file mode 100644 index 0000000000..e44cb48def --- /dev/null +++ b/examples/metdata/src/shared/data.ts @@ -0,0 +1,11 @@ +import { CustomMetadata } from './model'; + +export const customMetaData: CustomMetadata = { + a: 'custom', + b: 1, + c: { + d: 'nested', + }, +}; + + diff --git a/examples/metdata/src/shared/model.ts b/examples/metdata/src/shared/model.ts new file mode 100644 index 0000000000..1a9c259e05 --- /dev/null +++ b/examples/metdata/src/shared/model.ts @@ -0,0 +1,5 @@ +export type CustomMetadata = { + a: string; + b: number; + c: Object; +}; diff --git a/examples/metdata/tsconfig.json b/examples/metdata/tsconfig.json new file mode 100644 index 0000000000..372ba40607 --- /dev/null +++ b/examples/metdata/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ESNext", + "strict": true, + "jsx": "preserve", + "moduleResolution": "node", + "jsxImportSource": "@builder.io/mitosis" + }, + "include": ["src"] +} diff --git a/packages/core/src/__tests__/__snapshots__/alpine.test.ts.snap b/packages/core/src/__tests__/__snapshots__/alpine.test.ts.snap index 435fd037c3..09c985ebb8 100644 --- a/packages/core/src/__tests__/__snapshots__/alpine.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/alpine.test.ts.snap @@ -241,7 +241,10 @@ exports[`Alpine.js > jsx > Javascript Test > Basic Outputs 1`] = ` `; exports[`Alpine.js > jsx > Javascript Test > Basic Outputs Meta 1`] = ` -"
+"/** useMetadata: {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside +component\\"} */ + +
+" +`; + exports[`Alpine.js > jsx > Javascript Test > componentWithContext 1`] = ` "
@@ -1922,6 +1941,35 @@ exports[`Alpine.js > jsx > Javascript Test > expressionState 1`] = ` " `; +exports[`Alpine.js > jsx > Javascript Test > figmaMeta 1`] = ` +"/** useMetadata: +{\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 +Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon +Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ +Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ +Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive +State\\",\\"value\\":{\\"(Def) +Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) +Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) +Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} */ + + + +" +`; + exports[`Alpine.js > jsx > Javascript Test > getterState 1`] = ` "

@@ -3319,7 +3367,10 @@ exports[`Alpine.js > jsx > Typescript Test > Basic Outputs 1`] = ` `; exports[`Alpine.js > jsx > Typescript Test > Basic Outputs Meta 1`] = ` -"
+"/** useMetadata: {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside +component\\"} */ + +
+" +`; + exports[`Alpine.js > jsx > Typescript Test > componentWithContext 1`] = ` "
@@ -4989,6 +5056,35 @@ exports[`Alpine.js > jsx > Typescript Test > expressionState 1`] = ` " `; +exports[`Alpine.js > jsx > Typescript Test > figmaMeta 1`] = ` +"/** useMetadata: +{\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 +Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon +Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ +Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ +Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive +State\\",\\"value\\":{\\"(Def) +Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) +Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) +Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} */ + + + +" +`; + exports[`Alpine.js > jsx > Typescript Test > getterState 1`] = ` "

diff --git a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap index 5587defbd3..9eae1c7824 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap @@ -392,7 +392,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -3574,7 +3579,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -3852,6 +3862,41 @@ export class MyBasicComponentModule {} " `; +exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], +}) +export class ComplexMetaRawModule {} +" +`; + exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -3967,7 +4012,12 @@ export class RenderContentModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -4484,6 +4534,54 @@ export class MyComponentModule {} " `; +exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class FigmaButton { + @Input() icon; + @Input() interactiveState; + @Input() width; + @Input() size; + @Input() label; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], +}) +export class FigmaButtonModule {} +" +`; + exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -4774,7 +4872,12 @@ export class MyBasicComponentModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -5230,7 +5333,12 @@ export class OnUpdateWithDepsModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -7821,7 +7929,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -11271,7 +11384,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -11561,6 +11679,41 @@ export class MyBasicComponentModule {} " `; +exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], +}) +export class ComplexMetaRawModule {} +" +`; + exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -11684,7 +11837,12 @@ export class RenderContentModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -12226,6 +12384,54 @@ export class MyComponentModule {} " `; +exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class FigmaButton { + @Input() icon!: any; + @Input() interactiveState!: any; + @Input() width!: any; + @Input() size!: any; + @Input() label!: any; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], +}) +export class FigmaButtonModule {} +" +`; + exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -12533,7 +12739,12 @@ export class MyBasicComponentModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -13002,7 +13213,12 @@ export class OnUpdateWithDepsModule {} `; exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; diff --git a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap index 0fa4c40421..e240c67e28 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.mapper.test.ts.snap @@ -399,7 +399,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular with Import Mapper Tests > jsx > Javascript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -3624,7 +3629,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular with Import Mapper Tests > jsx > Javascript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -3909,6 +3919,42 @@ export class MyBasicComponentModule {} " `; +exports[`Angular with Import Mapper Tests > jsx > Javascript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], + bootstrap: [SomeOtherComponent], +}) +export class ComplexMetaRawModule {} +" +`; + exports[`Angular with Import Mapper Tests > jsx > Javascript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -4027,7 +4073,12 @@ export class RenderContentModule {} `; exports[`Angular with Import Mapper Tests > jsx > Javascript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -4552,6 +4603,55 @@ export class MyComponentModule {} " `; +exports[`Angular with Import Mapper Tests > jsx > Javascript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class FigmaButton { + @Input() icon; + @Input() interactiveState; + @Input() width; + @Input() size; + @Input() label; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], + bootstrap: [SomeOtherComponent], +}) +export class FigmaButtonModule {} +" +`; + exports[`Angular with Import Mapper Tests > jsx > Javascript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -4848,7 +4948,12 @@ export class MyBasicComponentModule {} `; exports[`Angular with Import Mapper Tests > jsx > Javascript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -5315,7 +5420,12 @@ export class OnUpdateWithDepsModule {} `; exports[`Angular with Import Mapper Tests > jsx > Javascript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -7954,7 +8064,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular with Import Mapper Tests > jsx > Typescript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -11447,7 +11562,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular with Import Mapper Tests > jsx > Typescript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -11744,6 +11864,42 @@ export class MyBasicComponentModule {} " `; +exports[`Angular with Import Mapper Tests > jsx > Typescript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], + bootstrap: [SomeOtherComponent], +}) +export class ComplexMetaRawModule {} +" +`; + exports[`Angular with Import Mapper Tests > jsx > Typescript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -11870,7 +12026,12 @@ export class RenderContentModule {} `; exports[`Angular with Import Mapper Tests > jsx > Typescript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -12420,6 +12581,55 @@ export class MyComponentModule {} " `; +exports[`Angular with Import Mapper Tests > jsx > Typescript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class FigmaButton { + @Input() icon!: any; + @Input() interactiveState!: any; + @Input() width!: any; + @Input() size!: any; + @Input() label!: any; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], + bootstrap: [SomeOtherComponent], +}) +export class FigmaButtonModule {} +" +`; + exports[`Angular with Import Mapper Tests > jsx > Typescript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -12735,7 +12945,12 @@ export class MyBasicComponentModule {} `; exports[`Angular with Import Mapper Tests > jsx > Typescript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -13215,7 +13430,12 @@ export class OnUpdateWithDepsModule {} `; exports[`Angular with Import Mapper Tests > jsx > Typescript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; diff --git a/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap index de23dc6e71..ca8e43d62e 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.state.test.ts.snap @@ -415,7 +415,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -3712,7 +3717,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -3988,6 +3998,41 @@ export class MyBasicComponentModule {} " `; +exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], +}) +export class ComplexMetaRawModule {} +" +`; + exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -4101,7 +4146,12 @@ export class RenderContentModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -4658,6 +4708,54 @@ export class MyComponentModule {} " `; +exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class FigmaButton { + @Input() icon; + @Input() interactiveState; + @Input() width; + @Input() size; + @Input() label; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], +}) +export class FigmaButtonModule {} +" +`; + exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -4974,7 +5072,12 @@ export class MyBasicComponentModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -5430,7 +5533,12 @@ export class OnUpdateWithDepsModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Javascript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -8095,7 +8203,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -11685,7 +11798,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -11973,6 +12091,41 @@ export class MyBasicComponentModule {} " `; +exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], +}) +export class ComplexMetaRawModule {} +" +`; + exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -12094,7 +12247,12 @@ export class RenderContentModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -12677,6 +12835,54 @@ export class MyComponentModule {} " `; +exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class FigmaButton { + @Input() icon!: any; + @Input() interactiveState!: any; + @Input() width!: any; + @Input() size!: any; + @Input() label!: any; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], +}) +export class FigmaButtonModule {} +" +`; + exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -13010,7 +13216,12 @@ export class MyBasicComponentModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -13479,7 +13690,12 @@ export class OnUpdateWithDepsModule {} `; exports[`Angular with manually creating and handling class properties as bindings (more stable) > jsx > Typescript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; diff --git a/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap index 48f5cc8285..e11df639ef 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.styles.test.ts.snap @@ -351,7 +351,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -3256,7 +3261,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -3503,6 +3513,34 @@ export class MyBasicComponentModule {} " `; +exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], +}) +export class ComplexMetaRawModule {} +" +`; + exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -3595,7 +3633,12 @@ export class RenderContentModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -4060,6 +4103,47 @@ export class MyComponentModule {} " `; +exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, +}) +export default class FigmaButton { + @Input() icon; + @Input() interactiveState; + @Input() width; + @Input() size; + @Input() label; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], +}) +export class FigmaButtonModule {} +" +`; + exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -4308,7 +4392,12 @@ export class MyBasicComponentModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -4691,7 +4780,12 @@ export class OnUpdateWithDepsModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Javascript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -6974,7 +7068,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -10147,7 +10246,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -10406,6 +10510,34 @@ export class MyBasicComponentModule {} " `; +exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], +}) +export class ComplexMetaRawModule {} +" +`; + exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -10506,7 +10638,12 @@ export class RenderContentModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -10996,6 +11133,47 @@ export class MyComponentModule {} " `; +exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, +}) +export default class FigmaButton { + @Input() icon!: any; + @Input() interactiveState!: any; + @Input() width!: any; + @Input() size!: any; + @Input() label!: any; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], +}) +export class FigmaButtonModule {} +" +`; + exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -11261,7 +11439,12 @@ export class MyBasicComponentModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -11657,7 +11840,12 @@ export class OnUpdateWithDepsModule {} `; exports[`Angular with visuallyIgnoreHostElement = false > jsx > Typescript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; diff --git a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap index 7c285bc01d..2f51bbbf88 100644 --- a/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/angular.test.ts.snap @@ -734,7 +734,12 @@ export default class MyBasicOutputsComponent { `; exports[`Angular > jsx > Javascript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -778,7 +783,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular > jsx > Javascript Test > Basic Outputs Meta 2`] = ` -"import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ @@ -6793,7 +6803,12 @@ export default class MyBasicForwardRefComponent { `; exports[`Angular > jsx > Javascript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -6834,7 +6849,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular > jsx > Javascript Test > basicForwardRefMetadata 2`] = ` -"import { Component } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { Component } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ @@ -7299,6 +7319,69 @@ export default class MyBasicComponent { " `; +exports[`Angular > jsx > Javascript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], +}) +export class ComplexMetaRawModule {} +" +`; + +exports[`Angular > jsx > Javascript Test > complexMeta 2`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { Component } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], + standalone: true, + imports: [CommonModule], +}) +export default class ComplexMetaRaw {} +" +`; + exports[`Angular > jsx > Javascript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -7505,7 +7588,12 @@ export default class RenderContent { `; exports[`Angular > jsx > Javascript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -7535,7 +7623,12 @@ export class MyComponentModule {} `; exports[`Angular > jsx > Javascript Test > customSelector 2`] = ` -"import { Component } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { Component } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ @@ -8484,6 +8577,95 @@ export default class MyComponent { " `; +exports[`Angular > jsx > Javascript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class FigmaButton { + @Input() icon; + @Input() interactiveState; + @Input() width; + @Input() size; + @Input() label; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], +}) +export class FigmaButtonModule {} +" +`; + +exports[`Angular > jsx > Javascript Test > figmaMeta 2`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { Component, Input } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], + standalone: true, + imports: [CommonModule], +}) +export default class FigmaButton { + @Input() icon; + @Input() interactiveState; + @Input() width; + @Input() size; + @Input() label; +} +" +`; + exports[`Angular > jsx > Javascript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -9021,7 +9203,12 @@ export default class MyBasicComponent { `; exports[`Angular > jsx > Javascript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -9058,7 +9245,12 @@ export class MyComponentModule {} `; exports[`Angular > jsx > Javascript Test > nativeAttributes 2`] = ` -"import { Component, Input } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { Component, Input } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ @@ -9856,7 +10048,12 @@ export default class OnUpdateWithDeps { `; exports[`Angular > jsx > Javascript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -9898,7 +10095,12 @@ export class MyComponentModule {} `; exports[`Angular > jsx > Javascript Test > outputEventBinding 2`] = ` -"import { Component } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { Component } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ @@ -14678,7 +14880,12 @@ export default class MyBasicOutputsComponent { `; exports[`Angular > jsx > Typescript Test > Basic Outputs Meta 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; @@ -14722,7 +14929,12 @@ export class MyBasicOutputsComponentModule {} `; exports[`Angular > jsx > Typescript Test > Basic Outputs Meta 2`] = ` -"import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside component\\"} + */ + +import { Output, EventEmitter, Component, Input } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ @@ -21273,7 +21485,12 @@ export default class MyBasicForwardRefComponent { `; exports[`Angular > jsx > Typescript Test > basicForwardRefMetadata 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -21319,7 +21536,12 @@ export class MyBasicForwardRefComponentModule {} `; exports[`Angular > jsx > Typescript Test > basicForwardRefMetadata 2`] = ` -"import { Component } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + +import { Component } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; export interface Props { @@ -21803,6 +22025,69 @@ export default class MyBasicComponent { " `; +exports[`Angular > jsx > Typescript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component } from \\"@angular/core\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class ComplexMetaRaw {} + +@NgModule({ + declarations: [ComplexMetaRaw], + imports: [CommonModule], + exports: [ComplexMetaRaw], +}) +export class ComplexMetaRawModule {} +" +`; + +exports[`Angular > jsx > Typescript Test > complexMeta 2`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + +import { Component } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +@Component({ + selector: \\"complex-meta-raw\\", + template: \` +
+ \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], + standalone: true, + imports: [CommonModule], +}) +export default class ComplexMetaRaw {} +" +`; + exports[`Angular > jsx > Typescript Test > componentWithContext 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -22025,7 +22310,12 @@ export default class RenderContent { `; exports[`Angular > jsx > Typescript Test > customSelector 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -22055,7 +22345,12 @@ export class MyComponentModule {} `; exports[`Angular > jsx > Typescript Test > customSelector 2`] = ` -"import { Component } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"selector\\":\\"not-my-component\\"}} + */ + +import { Component } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ @@ -23054,6 +23349,95 @@ export default class MyComponent { " `; +exports[`Angular > jsx > Typescript Test > figmaMeta 1`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { NgModule } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +import { Component, Input } from \\"@angular/core\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], +}) +export default class FigmaButton { + @Input() icon!: any; + @Input() interactiveState!: any; + @Input() width!: any; + @Input() size!: any; + @Input() label!: any; +} + +@NgModule({ + declarations: [FigmaButton], + imports: [CommonModule], + exports: [FigmaButton], +}) +export class FigmaButtonModule {} +" +`; + +exports[`Angular > jsx > Typescript Test > figmaMeta 2`] = ` +"/** + useMetadata: + {\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive State\\",\\"value\\":{\\"(Def) Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} + */ + +import { Component, Input } from \\"@angular/core\\"; +import { CommonModule } from \\"@angular/common\\"; + +@Component({ + selector: \\"figma-button\\", + template: \` + + \`, + styles: [ + \` + :host { + display: contents; + } + \`, + ], + standalone: true, + imports: [CommonModule], +}) +export default class FigmaButton { + @Input() icon!: any; + @Input() interactiveState!: any; + @Input() width!: any; + @Input() size!: any; + @Input() label!: any; +} +" +`; + exports[`Angular > jsx > Typescript Test > getterState 1`] = ` "import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @@ -23625,7 +24009,12 @@ export default class MyBasicComponent { `; exports[`Angular > jsx > Typescript Test > nativeAttributes 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component, Input } from \\"@angular/core\\"; @@ -23662,7 +24051,12 @@ export class MyComponentModule {} `; exports[`Angular > jsx > Typescript Test > nativeAttributes 2`] = ` -"import { Component, Input } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeAttributes\\":[\\"disabled\\"]}} + */ + +import { Component, Input } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ @@ -24486,7 +24880,12 @@ export default class OnUpdateWithDeps { `; exports[`Angular > jsx > Typescript Test > outputEventBinding 1`] = ` -"import { NgModule } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { NgModule } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; import { Component } from \\"@angular/core\\"; @@ -24528,7 +24927,12 @@ export class MyComponentModule {} `; exports[`Angular > jsx > Typescript Test > outputEventBinding 2`] = ` -"import { Component } from \\"@angular/core\\"; +"/** + useMetadata: + {\\"angular\\":{\\"nativeEvents\\":[\\"onFakeNative\\"]}} + */ + +import { Component } from \\"@angular/core\\"; import { CommonModule } from \\"@angular/common\\"; @Component({ diff --git a/packages/core/src/__tests__/__snapshots__/html.test.ts.snap b/packages/core/src/__tests__/__snapshots__/html.test.ts.snap index 754830f4af..8d57f9a86c 100644 --- a/packages/core/src/__tests__/__snapshots__/html.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/html.test.ts.snap @@ -825,7 +825,10 @@ exports[`Html > jsx > Javascript Test > Basic Outputs 1`] = ` `; exports[`Html > jsx > Javascript Test > Basic Outputs Meta 1`] = ` -"
+"/** useMetadata: {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside +component\\"} */ + +
+" +`; + exports[`Html > jsx > Javascript Test > getterState 1`] = ` "

@@ -8579,7 +8670,10 @@ exports[`Html > jsx > Typescript Test > Basic Outputs 1`] = ` `; exports[`Html > jsx > Typescript Test > Basic Outputs Meta 1`] = ` -"

+"/** useMetadata: {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside +component\\"} */ + +
+" +`; + exports[`Html > jsx > Typescript Test > getterState 1`] = ` "

diff --git a/packages/core/src/__tests__/__snapshots__/liquid.test.ts.snap b/packages/core/src/__tests__/__snapshots__/liquid.test.ts.snap index 4907f9241c..a34f841bd7 100644 --- a/packages/core/src/__tests__/__snapshots__/liquid.test.ts.snap +++ b/packages/core/src/__tests__/__snapshots__/liquid.test.ts.snap @@ -55,7 +55,10 @@ exports[`Liquid > jsx > Javascript Test > Basic Outputs 1`] = ` `; exports[`Liquid > jsx > Javascript Test > Basic Outputs Meta 1`] = ` -"

+"/** useMetadata: {\\"outputs\\":[\\"onMessage\\",\\"onEvent\\"],\\"baz\\":\\"metadata inside +component\\"} */ + +
" `; @@ -466,7 +469,9 @@ exports[`Liquid > jsx > Javascript Test > basicForwardRef 1`] = ` `; exports[`Liquid > jsx > Javascript Test > basicForwardRefMetadata 1`] = ` -"
+"/** useMetadata: {\\"forwardRef\\":\\"inputRef\\"} */ + +
" + + + + + + + + export let inputRef; + + + + + + + + + let name = 'PatrickJS'; + + + + + + + + + + + +
+ + " `; exports[`Svelte > jsx > Javascript Test > basicOnUpdateReturn 1`] = ` @@ -1753,6 +1809,47 @@ exports[`Svelte > jsx > Javascript Test > classState 1`] = ` " `; +exports[`Svelte > jsx > Javascript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + + + +
" +`; + exports[`Svelte > jsx > Javascript Test > componentWithContext 1`] = ` " + +" +`; + exports[`Svelte > jsx > Javascript Test > getterState 1`] = ` " -
" +
" `; exports[`Svelte > jsx > Typescript Test > BasicAttribute 1`] = ` @@ -5061,26 +5228,60 @@ exports[`Svelte > jsx > Typescript Test > basicForwardRef 1`] = ` `; exports[`Svelte > jsx > Typescript Test > basicForwardRefMetadata 1`] = ` -" +"/** + useMetadata: + {\\"forwardRef\\":\\"inputRef\\"} + */ + + + - let name = \\"PatrickJS\\"; - + + + +
+ + " `; exports[`Svelte > jsx > Typescript Test > basicOnUpdateReturn 1`] = ` @@ -5207,6 +5408,47 @@ exports[`Svelte > jsx > Typescript Test > classState 1`] = ` " `; +exports[`Svelte > jsx > Typescript Test > complexMeta 1`] = ` +"/** + useMetadata: + {\\"x\\":\\"y\\",\\"asdf\\":{\\"stringValue\\":\\"d\\",\\"booleanValue\\":true,\\"numberValue\\":1,\\"innerObject\\":{\\"stringValue\\":\\"inner\\",\\"numberValue\\":2,\\"booleanValue\\":false},\\"spreadStringValue\\":\\"f\\"}} + */ + + + +
" +`; + exports[`Svelte > jsx > Typescript Test > componentWithContext 1`] = ` " + +" +`; + exports[`Svelte > jsx > Typescript Test > getterState 1`] = ` "" `; +exports[`Vue > jsx > Javascript Test > figmaMeta 1`] = ` +"/** useMetadata: +{\\"figma\\":{\\"name\\":\\"def-button-beta-outlined\\",\\"url\\":\\"https://www.figma.com/xxx\\",\\"props\\":{\\"iconSmall\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 +Icon Small\\"},\\"iconMedium\\":{\\"type\\":\\"instance\\",\\"key\\":\\"📍 Icon +Medium\\"},\\"label\\":{\\"type\\":\\"string\\",\\"key\\":\\"✏️ +Label\\"},\\"icon\\":{\\"type\\":\\"boolean\\",\\"key\\":\\"👁️ +Icon\\",\\"value\\":{\\"false\\":false,\\"true\\":\\"placeholder\\"}},\\"interactiveState\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Interactive +State\\",\\"value\\":{\\"(Def) +Enabled\\":false,\\"Hovered\\":false,\\"Pressed\\":false,\\"Focused\\":false,\\"Disabled\\":\\"true\\"}},\\"size\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Size\\",\\"value\\":{\\"(Def) +Medium\\":false,\\"Small\\":\\"small\\"}},\\"width\\":{\\"type\\":\\"enum\\",\\"key\\":\\"Width\\",\\"value\\":{\\"(Def) +Auto Width\\":false,\\"Full Width\\":\\"full\\"}}}}} */ + + + +" +`; + exports[`Vue > jsx > Javascript Test > getterState 1`] = ` "