11/**
2- * @module useRegistry
2+ * @module createRegistry
33 *
4- * @see https://0.vuetifyjs.com/composables/registration/use -registry
4+ * @see https://0.vuetifyjs.com/composables/registration/create -registry
55 *
66 * @remarks
77 * A foundational composable for managing collections of items (tickets) with:
1717 */
1818
1919// Foundational
20- import { createContext } from '#v0/composables/createContext'
20+ import { createContext , useContext } from '#v0/composables/createContext'
2121import { createTrinity } from '#v0/composables/createTrinity'
2222
2323// Composables
@@ -29,7 +29,7 @@ import { shallowReactive } from 'vue'
2929
3030// Types
3131import type { ContextTrinity } from '#v0/composables/createTrinity'
32- import type { ID } from '#v0/types'
32+ import type { Extensible , ID } from '#v0/types'
3333import type { App } from 'vue'
3434
3535export interface RegistryTicket < V = unknown > {
@@ -51,8 +51,43 @@ export interface RegistryTicket<V = unknown> {
5151 valueIsIndex : boolean
5252}
5353
54+ /** Valid event names for registry operations */
55+ export type RegistryEventName =
56+ | 'register:ticket'
57+ | 'unregister:ticket'
58+ | 'update:ticket'
59+ | 'clear:registry'
60+ | 'reindex:registry'
61+
62+ /** Maps event names to their payload types */
63+ export type RegistryEventMap < Z extends RegistryTicket > = {
64+ 'register:ticket' : Z
65+ 'unregister:ticket' : Z
66+ 'update:ticket' : Z
67+ 'clear:registry' : undefined
68+ 'reindex:registry' : undefined
69+ }
70+
5471/** Callback signature for registry event listeners */
55- export type RegistryEventCallback = ( data : unknown ) => void
72+ export type RegistryEventCallback <
73+ Z extends RegistryTicket = RegistryTicket ,
74+ K extends RegistryEventName = RegistryEventName ,
75+ > = ( data : RegistryEventMap < Z > [ K ] ) => void
76+
77+ /** Resolves callback type: typed for known events, unknown for custom events */
78+ type EventHandler < Z extends RegistryTicket , K extends string > =
79+ K extends RegistryEventName
80+ ? ( data : RegistryEventMap < Z > [ K ] ) => void
81+ : ( data : unknown ) => void
82+
83+ /** Resolves payload type: typed for known events, unknown for custom events */
84+ type EventPayload < Z extends RegistryTicket , K extends string > =
85+ K extends RegistryEventName
86+ ? RegistryEventMap < Z > [ K ]
87+ : unknown
88+
89+ /** Internal callback type for event listeners storage */
90+ type InternalEventCallback = ( data : unknown ) => void
5691
5792export interface RegistryContext < Z extends RegistryTicket = RegistryTicket > {
5893 /**
@@ -150,7 +185,7 @@ export interface RegistryContext<Z extends RegistryTicket = RegistryTicket> {
150185 * const unique = registry.browse('unique-value') // ['ticket-3']
151186 * ```
152187 */
153- browse : ( value : unknown ) => ID [ ] | undefined
188+ browse : ( value : Z [ 'value' ] ) => ID [ ] | undefined
154189 /**
155190 * lookup a ticket by index number
156191 *
@@ -377,7 +412,7 @@ export interface RegistryContext<Z extends RegistryTicket = RegistryTicket> {
377412 * registry.register({ id: 'ticket-id' }) // Console: Ticket registered: { id: 'ticket-id', ... }
378413 * ```
379414 */
380- on : ( event : string , cb : RegistryEventCallback ) => void
415+ on : < K extends Extensible < RegistryEventName > > ( event : K , cb : EventHandler < Z , K > ) => void
381416 /**
382417 * Stop listening for registry events
383418 *
@@ -407,7 +442,7 @@ export interface RegistryContext<Z extends RegistryTicket = RegistryTicket> {
407442 * })
408443 * ```
409444 */
410- off : ( event : string , cb : RegistryEventCallback ) => void
445+ off : < K extends Extensible < RegistryEventName > > ( event : K , cb : EventHandler < Z , K > ) => void
411446 /**
412447 * Emit an event with data
413448 *
@@ -430,7 +465,7 @@ export interface RegistryContext<Z extends RegistryTicket = RegistryTicket> {
430465 * registry.emit('custom-event', { message: 'Hello, World!' }) // Console: Custom event received: { message: 'Hello, World!' }
431466 * ```
432467 */
433- emit : ( event : string , data : unknown ) => void
468+ emit : < K extends Extensible < RegistryEventName > > ( event : K , data : EventPayload < Z , K > ) => void
434469 /**
435470 * Clears the registry and removes all listeners
436471 *
@@ -632,7 +667,7 @@ export function createRegistry<
632667 const catalog = new Map < unknown , ID [ ] > ( )
633668 const directory = new Map < number , ID > ( )
634669 const cache = new Map < 'keys' | 'values' | 'entries' , unknown [ ] > ( )
635- const listeners = new Map < string , Set < RegistryEventCallback > > ( )
670+ const listeners = new Map < string , Set < InternalEventCallback > > ( )
636671
637672 let indexDependentCount = 0
638673 let needsReindex = false
@@ -647,7 +682,7 @@ export function createRegistry<
647682 for ( const cb of cbs ) cb ( data )
648683 }
649684
650- function on ( event : string , cb : RegistryEventCallback ) {
685+ function on ( event : string , cb : InternalEventCallback ) {
651686 if ( ! events ) {
652687 logger . warn ( `Events are disabled. Initialize with \`createRegistry({ events: true })\` to enable.` )
653688 return
@@ -657,7 +692,7 @@ export function createRegistry<
657692 listeners . get ( event ) ! . add ( cb )
658693 }
659694
660- function off ( event : string , cb : RegistryEventCallback ) {
695+ function off ( event : string , cb : InternalEventCallback ) {
661696 if ( ! events ) {
662697 logger . warn ( `Events are disabled. Initialize with \`createRegistry({ events: true })\` to enable.` )
663698 return
@@ -723,9 +758,7 @@ export function createRegistry<
723758 }
724759
725760 function browse ( value : unknown ) {
726- if ( indexDependentCount > 0 && needsReindex ) {
727- reindex ( )
728- }
761+ if ( needsReindex ) reindex ( )
729762 return catalog . get ( value )
730763 }
731764
@@ -933,7 +966,7 @@ export function createRegistry<
933966 const willReindex = indexDependentCount > 0 && ticket . index < collection . size
934967 if ( ! willReindex ) invalidate ( )
935968
936- emit ( 'unregister:ticket' , ticket )
969+ queueEmit ( 'unregister:ticket' , ticket )
937970
938971 minDirtyIndex = Math . min ( minDirtyIndex , ticket . index )
939972 if ( willReindex ) {
@@ -944,32 +977,32 @@ export function createRegistry<
944977 }
945978
946979 function offboard ( ids : ID [ ] ) {
947- const removed : Z [ ] = [ ]
980+ batch ( ( ) => {
981+ const removed : Z [ ] = [ ]
948982
949- for ( const id of ids ) {
950- const ticket = collection . get ( id )
951- if ( ! ticket ) continue
983+ for ( const id of ids ) {
984+ const ticket = collection . get ( id )
985+ if ( ! ticket ) continue
952986
953- if ( ticket . valueIsIndex ) {
954- indexDependentCount --
955- }
956-
957- minDirtyIndex = Math . min ( minDirtyIndex , ticket . index )
958- collection . delete ( ticket . id )
959- directory . delete ( ticket . index )
960- unassign ( ticket . value , ticket . id )
961- removed . push ( ticket )
962- }
987+ if ( ticket . valueIsIndex ) {
988+ indexDependentCount --
989+ }
963990
964- if ( removed . length === 0 ) return
991+ minDirtyIndex = Math . min ( minDirtyIndex , ticket . index )
992+ collection . delete ( ticket . id )
993+ directory . delete ( ticket . index )
994+ unassign ( ticket . value , ticket . id )
995+ removed . push ( ticket )
996+ }
965997
966- invalidate ( )
998+ if ( removed . length === 0 ) return
967999
968- for ( const ticket of removed ) {
969- queueEmit ( 'unregister:ticket' , ticket )
970- }
1000+ for ( const ticket of removed ) {
1001+ queueEmit ( 'unregister:ticket' , ticket )
1002+ }
9711003
972- needsReindex = true
1004+ needsReindex = true
1005+ } )
9731006 }
9741007
9751008 function seek (
@@ -1080,3 +1113,30 @@ export function createRegistryContext<
10801113
10811114 return createTrinity < E > ( useRegistryContext , provideRegistryContext , context )
10821115}
1116+
1117+ /**
1118+ * Uses an existing registry from context.
1119+ *
1120+ * @param namespace The namespace for the registry context. Defaults to `'v0:registry'`.
1121+ * @template Z The type of registry ticket that extends RegistryTicket.
1122+ * @template E The type of registry context that extends RegistryContext<Z>.
1123+ * @returns The registry instance.
1124+ *
1125+ * @see https://0.vuetifyjs.com/composables/registration/create-registry#use-registry
1126+ *
1127+ * @example
1128+ * ```ts
1129+ * import { useRegistry } from '@vuetify/v0'
1130+ *
1131+ * // In a child component (after provideRegistry was called by an ancestor):
1132+ * const registry = useRegistry()
1133+ *
1134+ * registry.register({ id: 'item-1', value: 'Value 1' })
1135+ * ```
1136+ */
1137+ export function useRegistry <
1138+ Z extends RegistryTicket = RegistryTicket ,
1139+ E extends RegistryContext < Z > = RegistryContext < Z > ,
1140+ > ( namespace = 'v0:registry' ) : E {
1141+ return useContext < E > ( namespace )
1142+ }
0 commit comments