-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Checkout UI extensions] Add Localized Fields API to Unstable
#2547
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
f651fb5
Adds UI extension `localizedFields` API and `useLocalizedFields` hook
rcaplanshopify 436df11
adds changelog
rcaplanshopify cc3f70f
adds localizedFields to CustomerAccountStandardApi interface
rcaplanshopify bb7cc99
adds docs for localized fields API
rcaplanshopify 2f6ef29
updates shared LocalizedFieldKey interface
rcaplanshopify File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@shopify/ui-extensions-react': minor | ||
'@shopify/ui-extensions': minor | ||
--- | ||
|
||
Adds the Localized Fields API and `useLocalizedFields` hook. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
packages/ui-extensions-react/src/surfaces/checkout/hooks/localized-fields.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import type { | ||
LocalizedField, | ||
LocalizedFieldKey, | ||
RenderExtensionTarget, | ||
} from '@shopify/ui-extensions/checkout'; | ||
|
||
import {ScopeNotGrantedError} from '../errors'; | ||
|
||
import {useApi} from './api'; | ||
import {useSubscription} from './subscription'; | ||
|
||
/** | ||
* Returns the current localized fields and | ||
* re-renders your component if the values change. | ||
*/ | ||
export function useLocalizedFields< | ||
Target extends RenderExtensionTarget = RenderExtensionTarget, | ||
>(keys: LocalizedFieldKey[]): LocalizedField[] | undefined { | ||
const {localizedFields} = useApi<Target>(); | ||
|
||
if (!localizedFields) { | ||
throw new ScopeNotGrantedError( | ||
'Using localized fields requires having personal customer data permissions granted to your app.', | ||
); | ||
} | ||
|
||
return useSubscription(localizedFields)?.filter(({key}) => | ||
keys.includes(key), | ||
); | ||
} |
78 changes: 78 additions & 0 deletions
78
packages/ui-extensions-react/src/surfaces/checkout/hooks/tests/localized-fields.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import type {LocalizedField} from '@shopify/ui-extensions/checkout'; | ||
|
||
import {useLocalizedFields} from '../localized-fields'; | ||
|
||
import {mount, createMockStatefulRemoteSubscribable} from './mount'; | ||
|
||
describe('useLocalizedFields', () => { | ||
it('throws an error if localized fields are not available', () => { | ||
const extensionApi = { | ||
localizedFields: undefined, | ||
}; | ||
|
||
expect(() => { | ||
mount.hook(() => useLocalizedFields(['TAX_CREDENTIAL_BR']), { | ||
extensionApi, | ||
}); | ||
}).toThrow( | ||
'Using localized fields requires having personal customer data permissions granted to your app.', | ||
); | ||
}); | ||
|
||
it('returns empty if no localized fields match the passed keys', () => { | ||
const localizedFields: LocalizedField[] = [ | ||
{ | ||
key: 'TAX_CREDENTIAL_BR', | ||
title: 'CPF/CNPJ', | ||
value: 'test-value', | ||
}, | ||
{ | ||
key: 'SHIPPING_CREDENTIAL_BR', | ||
title: 'CPF/CNPJ', | ||
value: 'test-value', | ||
}, | ||
]; | ||
|
||
const extensionApi = { | ||
localizedFields: createMockStatefulRemoteSubscribable(localizedFields), | ||
}; | ||
|
||
const {value} = mount.hook( | ||
() => useLocalizedFields(['TAX_CREDENTIAL_ES']), | ||
{extensionApi}, | ||
); | ||
|
||
expect(value).toStrictEqual([]); | ||
}); | ||
|
||
it('returns an array of localized fields that match the passsed keys', () => { | ||
const localizedFields: LocalizedField[] = [ | ||
{ | ||
key: 'TAX_CREDENTIAL_MX', | ||
title: 'Tax credential MX', | ||
value: 'test-value', | ||
}, | ||
{ | ||
key: 'SHIPPING_CREDENTIAL_MX', | ||
title: 'Shipping credential MX', | ||
value: 'test-value', | ||
}, | ||
{ | ||
key: 'TAX_CREDENTIAL_USE_MX', | ||
title: 'Tax credential use MX', | ||
value: 'test-value', | ||
}, | ||
]; | ||
|
||
const extensionApi = { | ||
localizedFields: createMockStatefulRemoteSubscribable(localizedFields), | ||
}; | ||
|
||
const {value} = mount.hook( | ||
() => useLocalizedFields(['TAX_CREDENTIAL_MX', 'TAX_CREDENTIAL_USE_MX']), | ||
{extensionApi}, | ||
); | ||
|
||
expect(value).toMatchObject([localizedFields[0], localizedFields[2]]); | ||
}); | ||
}); |
34 changes: 34 additions & 0 deletions
34
packages/ui-extensions/docs/surfaces/checkout/reference/apis/localized-fields.doc.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import type {ReferenceEntityTemplateSchema} from '@shopify/generate-docs'; | ||
|
||
import { | ||
getExample, | ||
getLinksByTag, | ||
STANDARD_API_PROPERTIES_DESCRIPTION, | ||
REQUIRES_PROTECTED_CUSTOMER_DATA, | ||
} from '../helper.docs'; | ||
|
||
const data: ReferenceEntityTemplateSchema = { | ||
name: 'Localized Fields', | ||
description: 'The API for interacting with localized fields.', | ||
isVisualComponent: false, | ||
requires: REQUIRES_PROTECTED_CUSTOMER_DATA, | ||
category: 'APIs', | ||
type: 'API', | ||
definitions: [ | ||
{ | ||
title: 'StandardApi', | ||
description: STANDARD_API_PROPERTIES_DESCRIPTION, | ||
type: 'Docs_Standard_LocalizedFieldsApi', | ||
}, | ||
{ | ||
title: 'useLocalizedFields', | ||
description: | ||
'Returns the current localized fields and re-renders your component if the values change.', | ||
type: 'UseLocalizedFieldsGeneratedType', | ||
}, | ||
], | ||
defaultExample: getExample('localized-fields/default', ['jsx', 'js']), | ||
related: getLinksByTag('apis'), | ||
}; | ||
|
||
export default data; |
45 changes: 45 additions & 0 deletions
45
...-extensions/docs/surfaces/checkout/reference/examples/localized-fields/default.example.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import {extension} from '@shopify/ui-extensions/checkout'; | ||
|
||
// 1. Choose an extension target | ||
export default extension( | ||
'purchase.checkout.block.render', | ||
(root, {buyerJourney, localizedFields}) => { | ||
let taxIdField; | ||
|
||
localizedFields?.subscribe( | ||
(localizedFields) => { | ||
// 2. Access localized field values | ||
taxIdField = localizedFields?.find( | ||
({key}) => | ||
key.startsWith('TAX_CREDENTIAL'), | ||
); | ||
}, | ||
); | ||
|
||
// 3. Validate localized field values | ||
buyerJourney.intercept( | ||
({canBlockProgress}) => { | ||
return canBlockProgress && | ||
taxIdField && | ||
(!taxIdField.value || | ||
taxIdField.value.length > 10) | ||
? { | ||
behavior: 'block', | ||
reason: 'Invalid tax ID', | ||
errors: [ | ||
{ | ||
message: `${taxIdField.title} is required and | ||
cannot exceed 10 characters in length`, | ||
// Show an error under the localized field or | ||
// exclude target to show at the top of the page | ||
target: `$.cart.localizedField.${taxIdField.key}`, | ||
}, | ||
], | ||
} | ||
: { | ||
behavior: 'allow', | ||
}; | ||
}, | ||
); | ||
}, | ||
); |
46 changes: 46 additions & 0 deletions
46
...extensions/docs/surfaces/checkout/reference/examples/localized-fields/default.example.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { | ||
reactExtension, | ||
useBuyerJourneyIntercept, | ||
useLocalizedFields, | ||
} from '@shopify/ui-extensions-react/checkout'; | ||
|
||
export default reactExtension( | ||
'purchase.checkout.block.render', | ||
() => <Extension />, | ||
); | ||
|
||
function Extension() { | ||
// 1. Access localized field values | ||
const localizedFields = useLocalizedFields([ | ||
'TAX_CREDENTIAL_BR', | ||
]); | ||
|
||
// 2. Access localized field values | ||
const taxIdField = localizedFields?.[0]; | ||
|
||
// 3. Validate localized field values | ||
useBuyerJourneyIntercept( | ||
({canBlockProgress}) => { | ||
return canBlockProgress && | ||
taxIdField && | ||
(!taxIdField.value || | ||
taxIdField.value.length > 10) | ||
? { | ||
behavior: 'block', | ||
reason: 'Invalid tax ID', | ||
errors: [ | ||
{ | ||
message: `${taxIdField.title} is required and | ||
cannot exceed 10 characters in length`, | ||
// Show an error under the localized field or | ||
// exclude target to show at the top of the page | ||
target: `$.cart.localizedField.${taxIdField.key}`, | ||
}, | ||
], | ||
} | ||
: { | ||
behavior: 'allow', | ||
}; | ||
}, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separating this comment prevents inclusion of the PR link in the docs and IDE.