diff --git a/packages/standard-components/src/forms/Form.svelte b/packages/standard-components/src/forms/Form.svelte index c229f30df8..9edb749088 100644 --- a/packages/standard-components/src/forms/Form.svelte +++ b/packages/standard-components/src/forms/Form.svelte @@ -3,6 +3,7 @@ import { setContext, getContext, onMount } from "svelte" import { writable, get } from "svelte/store" import { createValidatorFromConstraints } from "./validation" + import { generateID } from "../helpers" export let datasource export let theme @@ -82,9 +83,7 @@ const makeFieldState = (field, defaultValue) => { return writable({ field, - fieldId: `${Math.random() - .toString(32) - .substr(2)}/${field}`, + fieldId: `id-${generateID()}-${field}`, value: initialValues[field] ?? defaultValue, error: null, valid: true, diff --git a/packages/standard-components/src/helpers.js b/packages/standard-components/src/helpers.js index 02f3229467..af98473ac9 100644 --- a/packages/standard-components/src/helpers.js +++ b/packages/standard-components/src/helpers.js @@ -31,3 +31,35 @@ export const cssVars = (node, props) => { }, } } + +/** + * Generates a short random ID. + * This is "nanoid" but rollup was derping attempting to bundle it, so the + * source has just been extracted manually since it's tiny. + */ +export const generateID = (size = 21) => { + let id = "" + let bytes = crypto.getRandomValues(new Uint8Array(size)) + + // A compact alternative for `for (var i = 0; i < step; i++)`. + while (size--) { + // It is incorrect to use bytes exceeding the alphabet size. + // The following mask reduces the random byte in the 0-255 value + // range to the 0-63 value range. Therefore, adding hacks, such + // as empty string fallback or magic numbers, is unneccessary because + // the bitmask trims bytes down to the alphabet size. + let byte = bytes[size] & 63 + if (byte < 36) { + // `0-9a-z` + id += byte.toString(36) + } else if (byte < 62) { + // `A-Z` + id += (byte - 26).toString(36).toUpperCase() + } else if (byte < 63) { + id += "_" + } else { + id += "-" + } + } + return id +} diff --git a/packages/standard-components/yarn.lock b/packages/standard-components/yarn.lock index 3e5d933b3b..fd9043e58f 100644 --- a/packages/standard-components/yarn.lock +++ b/packages/standard-components/yarn.lock @@ -1768,6 +1768,11 @@ mri@^1.1.0: resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6" integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ== +nanoid@^3.1.20: + version "3.1.20" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" + integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== + node-releases@^1.1.60: version "1.1.60" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084"