@wix/zero-config-implementation 1.96.0 → 1.97.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "registry": "https://registry.npmjs.org/",
5
5
  "access": "public"
6
6
  },
7
- "version": "1.96.0",
7
+ "version": "1.97.0",
8
8
  "description": "Core library for extracting component manifests from JS and CSS files",
9
9
  "type": "module",
10
10
  "main": "dist/index.js",
@@ -106,5 +106,5 @@
106
106
  ]
107
107
  }
108
108
  },
109
- "falconPackageHash": "d3a6a9c74757e90d4bf8667577b7d75107131acdedfc47058f1a69da"
109
+ "falconPackageHash": "0b3ebaeffed6f192d5ccd84f8598e0e524b0edb36eb3ca0961bab4c7"
110
110
  }
@@ -0,0 +1,32 @@
1
+ import { DATA } from '@wix/react-component-schema'
2
+ import { describe, expect, it } from 'vitest'
3
+ import type { PropWriteInfo, TrackingStores } from '../information-extractors/react/types'
4
+ import { collectUsedA11yAttributes } from './a11y-builder'
5
+
6
+ function propUsagesFor(propPaths: string[]): TrackingStores['propUsages'] {
7
+ const emptyWriteInfo = (): PropWriteInfo => ({ elements: new Map(), attributes: new Map() })
8
+ return new Map(propPaths.map((propPath) => [propPath, emptyWriteInfo()]))
9
+ }
10
+
11
+ describe('collectUsedA11yAttributes', () => {
12
+ it('returns an empty array when propUsages or propPath is unavailable', () => {
13
+ expect(collectUsedA11yAttributes(undefined, 'props.a11y')).toEqual([])
14
+ expect(collectUsedA11yAttributes(propUsagesFor(['props.a11y.role']), undefined)).toEqual([])
15
+ })
16
+
17
+ it('returns an empty array when no accessibility fields are recorded', () => {
18
+ expect(collectUsedA11yAttributes(propUsagesFor([]), 'props.a11y')).toEqual([])
19
+ })
20
+
21
+ it('allows only the current editor-configurable fields', () => {
22
+ const allAttributes = Object.values(DATA.A11Y_ATTRIBUTES).map((attribute) => `props.a11y.${attribute}`)
23
+
24
+ expect(collectUsedA11yAttributes(propUsagesFor(allAttributes), 'props.a11y')).toEqual(['ariaLabel', 'tag'])
25
+ })
26
+
27
+ it('keeps allowed fields in schema order', () => {
28
+ const propUsages = propUsagesFor(['props.a11y.tag', 'props.a11y.role', 'props.a11y.ariaLabel'])
29
+
30
+ expect(collectUsedA11yAttributes(propUsages, 'props.a11y')).toEqual(['ariaLabel', 'tag'])
31
+ })
32
+ })
@@ -1,25 +1,31 @@
1
1
  import { DATA } from '@wix/react-component-schema'
2
2
  import type { TrackingStores } from '../information-extractors/react'
3
3
 
4
+ type A11yAttribute = (typeof DATA.A11Y_ATTRIBUTES)[keyof typeof DATA.A11Y_ATTRIBUTES]
5
+
6
+ const EDITOR_CONFIGURABLE_A11Y_ATTRIBUTES: ReadonlySet<A11yAttribute> = new Set([
7
+ DATA.A11Y_ATTRIBUTES.ariaLabel,
8
+ DATA.A11Y_ATTRIBUTES.tag,
9
+ ])
10
+
4
11
  /**
5
- * Walks the known A11y attributes (from DATA.A11Y_ATTRIBUTES) in deterministic
6
- * enum order and returns the subset whose `${propPath}.${attribute}` key was
7
- * recorded in propUsages by the prop-tracker. When propUsages or propPath is
8
- * unavailable, returns an empty array — per the schema, an empty list means
9
- * "all possible A11Y values", which is a safe default.
12
+ * Returns the editor-configurable attributes the component reads, in schema
13
+ * order. The caller must omit the a11y data item when this returns an empty
14
+ * list because the manifest schema interprets an empty list as all attributes.
10
15
  */
11
16
  export function collectUsedA11yAttributes(
12
17
  propUsages: TrackingStores['propUsages'] | undefined,
13
18
  propPath: string | undefined,
14
- ): (typeof DATA.A11Y_ATTRIBUTES)[keyof typeof DATA.A11Y_ATTRIBUTES][] {
19
+ ): A11yAttribute[] {
15
20
  if (!propUsages || !propPath) return []
16
21
 
17
- const used: (typeof DATA.A11Y_ATTRIBUTES)[keyof typeof DATA.A11Y_ATTRIBUTES][] = []
22
+ const usedAttributes: A11yAttribute[] = []
18
23
  for (const attribute of Object.values(DATA.A11Y_ATTRIBUTES)) {
19
- if (attribute === DATA.A11Y_ATTRIBUTES.Unknown_AriaAttributes) continue
24
+ if (!EDITOR_CONFIGURABLE_A11Y_ATTRIBUTES.has(attribute)) continue
20
25
  if (propUsages.has(`${propPath}.${attribute}`)) {
21
- used.push(attribute)
26
+ usedAttributes.push(attribute)
22
27
  }
23
28
  }
24
- return used
29
+
30
+ return usedAttributes
25
31
  }
@@ -54,6 +54,45 @@ function createComponent(rootElement: ExtractedElement): ComponentInfoWithCss {
54
54
  }
55
55
  }
56
56
 
57
+ function createComponentWithA11yUsages(propPaths: string[]): ComponentInfoWithCss {
58
+ return {
59
+ ...createComponent(createElementWithDisplayMatcher('div', matcherDataFromCss(''))),
60
+ props: {
61
+ a11y: {
62
+ name: 'a11y',
63
+ type: 'A11y',
64
+ required: false,
65
+ resolvedType: { kind: 'semantic', value: 'A11y', source: '@wix/editor-react-types' },
66
+ propPath: 'props.a11y',
67
+ logicOnly: false,
68
+ },
69
+ },
70
+ propUsages: new Map(propPaths.map((propPath) => [propPath, { elements: new Map(), attributes: new Map() }])),
71
+ }
72
+ }
73
+
74
+ describe('toEditorReactComponent accessibility conversion', () => {
75
+ it('omits the a11y item when the component reads only component-owned fields', () => {
76
+ const component = createComponentWithA11yUsages(['props.a11y.role', 'props.a11y.tabIndex'])
77
+
78
+ expect(toEditorReactComponent(component).editorElement?.data?.a11y).toBeUndefined()
79
+ })
80
+
81
+ it('emits only the allowed fields when reads are mixed', () => {
82
+ const component = createComponentWithA11yUsages([
83
+ 'props.a11y.role',
84
+ 'props.a11y.ariaLabel',
85
+ 'props.a11y.ariaExpanded',
86
+ 'props.a11y.tag',
87
+ ])
88
+
89
+ expect(toEditorReactComponent(component).editorElement?.data?.a11y).toMatchObject({
90
+ dataType: 'a11y',
91
+ a11y: { attributes: ['ariaLabel', 'tag'] },
92
+ })
93
+ })
94
+ })
95
+
57
96
  function createSemanticElement({
58
97
  traceId,
59
98
  name,
@@ -10,7 +10,7 @@ import type {
10
10
  ElementItem,
11
11
  States,
12
12
  } from '@wix/react-component-schema'
13
- import { CSS_PROPERTIES, ELEMENTS } from '@wix/react-component-schema'
13
+ import { CSS_PROPERTIES, DATA, ELEMENTS } from '@wix/react-component-schema'
14
14
  import { camelCase } from 'case-anything'
15
15
  import { IoError } from '../errors'
16
16
  import { buildRefElementManifestKey } from '../extensions/ref-elements/path-utils'
@@ -184,6 +184,7 @@ function buildData(
184
184
 
185
185
  const result = buildDataItem(prop, defaultValue, propUsages, prop.propPath)
186
186
  if (result.isErr()) throw result.error
187
+ if (result.value.dataType === DATA.DATA_TYPE.a11y && !result.value.a11y?.attributes?.length) continue
187
188
  // ActiveItemIndex props default to 0 when no default is specified
188
189
  if (prop.activeItemIndexTarget && result.value.defaultValue === undefined) {
189
190
  result.value.defaultValue = 0