From 054367a84c4af22740796bbba9a8c2842b360a18 Mon Sep 17 00:00:00 2001 From: Theo Date: Sun, 16 Nov 2025 02:13:33 -0800 Subject: [PATCH] Allowing customization of ids --- packages/tlschema/src/records/TLShape.ts | 8 +++-- packages/utils/src/index.ts | 7 +++- packages/utils/src/lib/id.ts | 42 ++++++++++++++++++++---- 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/packages/tlschema/src/records/TLShape.ts b/packages/tlschema/src/records/TLShape.ts index ba561d3e11a8..d0f679838b1d 100644 --- a/packages/tlschema/src/records/TLShape.ts +++ b/packages/tlschema/src/records/TLShape.ts @@ -410,13 +410,13 @@ export function isShapeId(id?: string): id is TLShapeId { /** * Creates a new shape ID. * - * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated + * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated. * @returns A new shape ID with the "shape:" prefix * * @example * ```ts * // Create a shape with auto-generated ID - * const shapeId = createShapeId() // "shape:abc123" + * const shapeId = createShapeId() // "shape:V1StGXR8_Z5jdHi6B-myT" * * // Create a shape with custom ID * const customShapeId = createShapeId('my-rectangle') // "shape:my-rectangle" @@ -431,6 +431,10 @@ export function isShapeId(id?: string): id is TLShapeId { * } * ``` * + * @remarks + * To customize ID generation (e.g., shorter IDs), use {@link setUniqueIdGenerator} from `@tldraw/utils`. + * This affects all ID generation across tldraw, including shapes, pages, and other records. + * * @public */ export function createShapeId(id?: string): TLShapeId { diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 2831ffd7fa7e..9df4270ad0b8 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -33,7 +33,12 @@ export { ExecutionQueue } from './lib/ExecutionQueue' export { FileHelpers } from './lib/file' export { noop, omitFromStackTrace } from './lib/function' export { getHashForBuffer, getHashForObject, getHashForString, lns } from './lib/hash' -export { mockUniqueId, restoreUniqueId, uniqueId } from './lib/id' +export { + mockUniqueId, + restoreUniqueId, + setUniqueIdGenerator, + uniqueId, +} from './lib/id' export { getFirstFromIterable } from './lib/iterable' export type { JsonArray, JsonObject, JsonPrimitive, JsonValue } from './lib/json-value' export { diff --git a/packages/utils/src/lib/id.ts b/packages/utils/src/lib/id.ts index c02306926638..759b2e4be9eb 100644 --- a/packages/utils/src/lib/id.ts +++ b/packages/utils/src/lib/id.ts @@ -55,6 +55,36 @@ function nanoid(size = 21) { } let impl = nanoid + +/** + * Override the unique ID generator with a custom implementation. + * + * This allows you to customize how IDs are generated across tldraw. This affects + * all ID generation including shapes, pages, and other records. + * + * @param fn - The custom function that should return a string ID. Takes optional size parameter. + * @example + * ```ts + * import { setUniqueIdGenerator, restoreUniqueId } from '@tldraw/utils' + * + * // Use a completely custom ID format + * setUniqueIdGenerator(() => `id-${Date.now()}-${Math.random()}`) + * + * // Or implement your own generator with a specific size + * setUniqueIdGenerator((size = 10) => { + * // Your custom ID generation logic here + * return 'custom-id-' + size + * }) + * + * // Restore original implementation + * restoreUniqueId() + * ``` + * @public + */ +export function setUniqueIdGenerator(fn: (size?: number) => string) { + impl = fn +} + /** * Mock the unique ID generator with a custom implementation for testing. * @@ -79,21 +109,21 @@ export function mockUniqueId(fn: (size?: number) => string) { } /** - * Restore the original unique ID generator after mocking. + * Restore the original unique ID generator. * * Resets the ID generation function back to the original nanoid implementation. - * This should be called after testing to restore normal ID generation behavior. + * This should be called after testing or customizing to restore normal ID generation behavior. * * @example * ```ts - * // After mocking for tests - * mockUniqueId(() => 'mock-id') + * // After customizing for your app + * setUniqueIdGenerator((size = 10) => nanoid(size)) * * // Restore original behavior * restoreUniqueId() - * console.log(uniqueId()) // Now generates real random IDs again + * console.log(uniqueId()) // Now generates real random IDs again (21 chars) * ``` - * @internal + * @public */ export function restoreUniqueId() { impl = nanoid