Skip to content

Commit

Permalink
Merge pull request #4 from vtex-apps/feature/migration
Browse files Browse the repository at this point in the history
Feature/migration
  • Loading branch information
lbebber authored Oct 3, 2019
2 parents c9ac280 + 89d81ac commit e2e0446
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- `migrationFrom` option.

## [0.2.1] - 2019-10-03
### Changed
Expand Down
13 changes: 12 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Utility for generating CSS handles for store components.

🚧 Under Construction 🚧

### Usage
## Usage

```tsx
import React, { FunctionComponent } from 'react'
Expand Down Expand Up @@ -35,3 +35,14 @@ const Component: FunctionComponent = () => {
)
}
```

### Options

- `migrationFrom`: Adds additional CSS handles for cases where a component is migrating from another app.

#### Usage:
```tsx
const CSS_HANDLES = ['container']
const handles = useCssHandles(CSS_HANDLES, { migrationFrom: '[email protected]' })
// Returns { container: 'vtex-current-app-0-x-container vtex-store-components-3-x-container' }
```
19 changes: 19 additions & 0 deletions react/__tests__/useCssHandles.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,24 @@ describe('useCssHandles', () => {
'vtex-app-2-x-element2 vtex-app-2-x-element2--blockClass vtex-previous-app-2-x-element2 vtex-previous-app-2-x-element2--blockClass vtex-previous-app-3-x-element2 vtex-previous-app-3-x-element2--blockClass',
})
})

it('doesnt repeat the migration if the current app happens to be the same as the migration one', () => {
const CSS_HANDLES = ['element1', 'element2']

const handles = useCssHandles(CSS_HANDLES, {
migrationFrom: [
'[email protected]',
'[email protected]',
'[email protected]',
],
})

expect(handles).toStrictEqual({
element1:
'vtex-app-2-x-element1 vtex-app-2-x-element1--blockClass vtex-previous-app-2-x-element1 vtex-previous-app-2-x-element1--blockClass vtex-previous-app-3-x-element1 vtex-previous-app-3-x-element1--blockClass',
element2:
'vtex-app-2-x-element2 vtex-app-2-x-element2--blockClass vtex-previous-app-2-x-element2 vtex-previous-app-2-x-element2--blockClass vtex-previous-app-3-x-element2 vtex-previous-app-3-x-element2--blockClass',
})
})
})
})
45 changes: 33 additions & 12 deletions react/useCssHandles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ interface CssHandlesOptions {
migrationFrom?: string | string[]
}

const generateCssHandles = <T extends CssHandlesInput>(
component: string,
handles: T,
modifiers?: string | string[]
) => {
const parseComponentName = (componentName: string) => {
/* Matches until the first `.` or `@`.
* Used to split something like `[email protected]` into
* `vtex`, `style-guide`, and `2`. */
Expand All @@ -23,12 +19,24 @@ const generateCssHandles = <T extends CssHandlesInput>(
* provides 3 different results. Yeah I know.
* There exists a `String.matchAll()` function but it's not
* supported on Safari */
const [vendor] = splitAppName.exec(component) || [null]
const [name] = splitAppName.exec(component) || [null]
const [major] = splitAppName.exec(component) || [null]
const [vendor] = splitAppName.exec(componentName) || [null]
const [name] = splitAppName.exec(componentName) || [null]
const [major] = splitAppName.exec(componentName) || [null]

const namespace = vendor && name && major && `${vendor}-${name}-${major}-x`
return { vendor, name, major }
}

const normalizeComponentName = (componentName: string) => {
const { vendor, name, major } = parseComponentName(componentName)

return vendor && name && major && `${vendor}-${name}-${major}-x`
}

const generateCssHandles = <T extends CssHandlesInput>(
namespace: string,
handles: T,
modifiers?: string | string[]
) => {
return handles.reduce<Record<string, string>>((acc, handle) => {
const isValid = !!namespace && validateCssHandle(handle)
const transformedHandle = `${namespace}-${handle}`
Expand Down Expand Up @@ -66,11 +74,24 @@ const useCssHandles = <T extends CssHandlesInput>(

const values = useMemo<CssHandles<T>>(() => {
const { migrationFrom } = options
const components = [component]
const normalizedComponent = normalizeComponentName(component)

const namespaces = normalizedComponent ? [normalizedComponent] : []
if (migrationFrom) {
components.push(...([] as string[]).concat(migrationFrom))
const migrations = Array.isArray(migrationFrom)
? migrationFrom
: [migrationFrom]

const normalizedMigrations = migrations
.map(normalizeComponentName)
.filter(
current => !!current && current !== normalizedComponent
) as string[]

namespaces.push(...normalizedMigrations)
}
return components

return namespaces
.map(component => generateCssHandles(component, handles, blockClass))
.reduce<CssHandles<T>>(
(acc: null | CssHandles<T>, cur: CssHandles<T>) => {
Expand Down

0 comments on commit e2e0446

Please sign in to comment.