Skip to content

Add nanoid, remove deprecated shortId #3170

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

Merged
merged 1 commit into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions components/component-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1403,7 +1403,11 @@
}
},
"required": false,
"description": "Event Callbacks\n* `onClickBack`: Called when the Back link is clicked.\n* `onClickHelp`: Called when the Help link is clicked.\n_Tested with Mocha testing._"
"description": "Event Callbacks\n* `onClickBack`: Called when the Back link is clicked.\n* `onClickHelp`: Called when the Help link is clicked.\n_Tested with Mocha testing._",
"defaultValue": {
"value": "{}",
"computed": false
}
},
"iconCategory": {
"type": {
Expand Down Expand Up @@ -9233,11 +9237,7 @@
}
},
"required": false,
"description": "**Assistive text for accessibility.**\n* `activeDescriptor`: The text that appears alongside a link that is currently active.",
"defaultValue": {
"value": "{\n\tactiveDescriptor: 'Current page:',\n}",
"computed": false
}
"description": "**Assistive text for accessibility.**\n* `activeDescriptor`: The text that appears alongside a link that is currently active."
},
"className": {
"type": {
Expand Down Expand Up @@ -9279,11 +9279,7 @@
"name": "string"
},
"required": false,
"description": "The `href` attribute of the link. Please pass in bookmarkable URLs from your routing library. Use `GlobalNavigationBarButton` if a \"real URL\" is not desired. If the `onClick` callback is specified this URL will still be prevented from changing the browser's location.",
"defaultValue": {
"value": "'#'",
"computed": false
}
"description": "The `href` attribute of the link. Please pass in bookmarkable URLs from your routing library. Use `GlobalNavigationBarButton` if a \"real URL\" is not desired. If the `onClick` callback is specified this URL will still be prevented from changing the browser's location."
},
"id": {
"type": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1923,7 +1923,7 @@ exports[`Datepicker
required={false}
role="textbox"
type="text"
value="2014"
value=""
/>
<span
className="slds-icon_container slds-input__icon slds-input__icon_right"
Expand Down Expand Up @@ -2783,7 +2783,7 @@ exports[`Datepicker Default DOM Snapshot 1`] = `
required={false}
role="textbox"
type="text"
value="2014"
value=""
/>
<span
className="slds-icon_container slds-input__icon slds-input__icon_right"
Expand Down Expand Up @@ -3486,7 +3486,7 @@ exports[`Datepicker Default HTML Snapshot 1`] = `
<div class=\\"slds-form-element__control\\">
<div class=\\"slds-combobox_container\\">
<div class=\\"slds-combobox slds-dropdown-trigger slds-dropdown-trigger_click ignore-react-onclickoutside slds-shrink-none\\" role=\\"combobox\\" aria-expanded=\\"false\\" aria-haspopup=\\"listbox\\">
<div class=\\"slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right\\" role=\\"none\\"><input type=\\"text\\" autoComplete=\\"off\\" class=\\"slds-input slds-combobox__input\\" id=\\"sample-datepicker-year-picklist\\" placeholder=\\"Select an Option\\" readonly=\\"\\" role=\\"textbox\\" aria-autocomplete=\\"list\\" value=\\"2014\\" /><span class=\\"slds-icon_container slds-input__icon slds-input__icon_right\\"><svg aria-hidden=\\"true\\" class=\\"slds-icon slds-icon_x-small slds-icon-text-default\\">
<div class=\\"slds-combobox__form-element slds-input-has-icon slds-input-has-icon_right\\" role=\\"none\\"><input type=\\"text\\" autoComplete=\\"off\\" class=\\"slds-input slds-combobox__input\\" id=\\"sample-datepicker-year-picklist\\" placeholder=\\"Select an Option\\" readonly=\\"\\" role=\\"textbox\\" aria-autocomplete=\\"list\\" value=\\"\\" /><span class=\\"slds-icon_container slds-input__icon slds-input__icon_right\\"><svg aria-hidden=\\"true\\" class=\\"slds-icon slds-icon_x-small slds-icon-text-default\\">
<use href=\\"/assets/icons/utility-sprite/svg/symbols.svg#down\\"></use>
</svg></span></div>
</div>
Expand Down Expand Up @@ -3749,7 +3749,7 @@ exports[`ErrorPicker 1`] = `
required={false}
role="textbox"
type="text"
value="2014"
value=""
/>
<span
className="slds-icon_container slds-input__icon slds-input__icon_right"
Expand Down
34 changes: 13 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"lodash.isfunction": "^3.0.9",
"lodash.reject": "^4.6.0",
"memoize-one": "^6.0.0",
"nanoid": "^5.0.9",
"popper.js": "^1.10.8",
"prop-types": ">=15.7.2",
"react-contenteditable": "^3.3.5",
Expand All @@ -108,7 +109,6 @@
"react-onclickoutside": "^6.10.0",
"react-required-if": "^1.0.3",
"react-text-truncate": "^0.19.0",
"shortid": "^2.2.15",
"warning": "^4.0.3"
},
"peerDependencies": {
Expand Down
14 changes: 14 additions & 0 deletions tests/__mocks__/nanoid-mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function getUniqueMockNanoId() {
const randomString = Array.from({ length: 10 }, () => {
const isUppercase = Math.random() < 0.5;
const charCode = isUppercase
? 65 + Math.floor(Math.random() * 26)
: 97 + Math.floor(Math.random() * 26);
return String.fromCharCode(charCode);
}).join('');
return `mockId_${randomString}`;
}

module.exports = function generateId() {
return getUniqueMockNanoId();
};
4 changes: 2 additions & 2 deletions tests/story-based-tests.accessibility-test.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"testEnvironment": "node",
"setupFilesAfterEnv": ["<rootDir>/tests/axe-puppeteer-matcher.js"],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/tests/__mocks__/file-mock.js"
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/tests/__mocks__/file-mock.js",
".*/utilities/generate-id$": "<rootDir>/tests/__mocks__/nanoid-mock.js"
},
"setupFiles": [
"<rootDir>/.jest/register-context.js",
Expand Down
5 changes: 3 additions & 2 deletions tests/story-based-tests.dom-snapshot-test.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"testRegex": "/(components|tests)/.*\\.dom-snapshot-test\\.jsx?$",
"testEnvironment": "node",
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/tests/__mocks__/file-mock.js"
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/tests/__mocks__/file-mock.js",
".*/utilities/generate-id$": "<rootDir>/tests/__mocks__/nanoid-mock.js"
},
"setupFiles": [
"<rootDir>/.jest/register-context.js",
Expand All @@ -16,6 +16,7 @@
"/.tmp-amd/",
"/.tmp-commonjs/",
"/.tmp-es/",
"/.tmp-esm/",
"/.tmp-npm/"
],
"transform": {
Expand Down
5 changes: 3 additions & 2 deletions tests/story-based-tests.snapshot-test.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"testRegex": "/(components|tests)/.*\\.snapshot-test\\.jsx?$",
"testEnvironment": "node",
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/tests/__mocks__/file-mock.js"
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/tests/__mocks__/file-mock.js",
".*/utilities/generate-id$": "<rootDir>/tests/__mocks__/nanoid-mock.js"
},
"setupFiles": [
"<rootDir>/.jest/register-context.js",
Expand All @@ -16,6 +16,7 @@
"/.tmp-amd/",
"/.tmp-commonjs/",
"/.tmp-es/",
"/.tmp-esm/",
"/.tmp-npm/"
],
"transform": {
Expand Down
9 changes: 4 additions & 5 deletions utilities/generate-id.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
import shortid from 'shortid';
import { nanoid } from 'nanoid';

/**
* Generate unique ID that is also a valid CSS identifier.
* @returns {string} The unique ID.
*/
function generateId() {
/**
* `shortid.generate()` by itself will generates IDs that
* `nanoid()` by itself will generates IDs that
* are not always valid [1] CSS identifiers (e.g. will start
* with a digit). So, when other parts of the codebase will
* use those IDs as a selector, a `SyntaxError`² will be thrown
* (i.e. `'#...' is not a valid selector`).
*
* The `slds-` prefix is used so to keep things simple.
* `shortid.characters()` requires "a string of all 64 unique
* `nanoid()` requires "a string of all 64 unique
* characters"³, which means that in order to generate valid
* CSS identifiers a-z, A-Z, and some "ISO 10646 characters
* U+00A0 and higher"¹ will need to be included.
*
* [1] https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
* [2] https://dom.spec.whatwg.org/#selectors
* [3] https://github.com/dylang/shortid/blob/937ce2c8dd7001baec1785cb8dce6e6fe1bcf61f/README.md#shortidcharactersstring
*/

return `slds-${shortid.generate()}`;
return `slds-${nanoid()}`;
}

export default generateId;