{"version":3,"file":"group.mjs","sources":["../../../../src/lib/group/group.mts"],"sourcesContent":["import { createGroupStores } from '../shared/stores.mjs';\nimport { createForm } from '../form/form.mjs';\n\nimport type { BeakerStores, BeakerOptions, FormulaOptions } from '../shared/types.mjs';\nimport type { Formula } from '../form/form.mjs';\n\nexport interface Beaker {\n  group: (node: HTMLElement) => { destroy: () => void };\n  update: (options: FormulaOptions) => void;\n  destroy: () => void;\n  forms: Map<HTMLElement, Formula>;\n  stores: BeakerStores;\n  init: (items: Array<Record<string, unknown>>) => void;\n  add: (item: Record<string, unknown>) => void;\n  set: (index: number, item: Record<string, unknown>) => void;\n  delete: (index: number) => void;\n  clear: () => void;\n}\n\n/**\n * Type for dynamic store access - provides get/set methods for any store value\n */\ntype StoreAccessor = Record<string, { get: () => unknown; set: (value: unknown) => void }>;\n\n/**\n * Helper to get a value from a store by key\n */\nfunction getStoreValue(stores: BeakerStores, key: string): unknown {\n  return (stores as StoreAccessor)[key].get();\n}\n\n/**\n * Helper to set a value on a store by key\n */\nfunction setStoreValue(stores: BeakerStores, key: string, value: unknown): void {\n  (stores as StoreAccessor)[key].set(value);\n}\n\nlet groupCounter = 0;\n\nexport function createGroup(options: BeakerOptions, beakerStores: Map<string, BeakerStores>): Beaker {\n  const groupStores = createGroupStores(options);\n  let groupName: string;\n  let globalObserver: MutationObserver;\n\n  const { defaultValues = [], ...formulaOptions } = options || {};\n\n  const formulaInstances = new Map<HTMLElement, Formula>();\n  const formInstances = new Map<HTMLElement, { root: HTMLElement; elements: Array<[string, HTMLElement[]]>; destroy: () => void }>();\n  const subscriptions = new Set<() => void>();\n\n  function destroyGroup() {\n    formInstances.forEach((instance) => instance.destroy());\n    subscriptions.forEach((sub) => sub());\n    formInstances.clear();\n    formulaInstances.clear();\n    subscriptions.clear();\n  }\n\n  function cleanupStores(rows: Element[]) {\n    for (const key of Object.keys(groupStores)) {\n      if (['formValues', 'initialValues', 'submitValues'].includes(key)) continue;\n      const state = getStoreValue(groupStores, key);\n      setStoreValue(groupStores, key, Array.isArray(state) ? state.slice(0, rows.length) : state);\n    }\n  }\n\n  function setupSubscriptions(form: Formula, index: number) {\n    const formStores = Object.entries(form.stores) as Array<[string, { subscribe: (fn: (value: unknown) => void) => () => void }]>;\n    for (const [key, store] of formStores) {\n      let initial = true;\n      const unsub = store.subscribe((value) => {\n        if (initial && key === 'formValues') {\n          initial = false;\n          return;\n        }\n        initial = false;\n        const state = getStoreValue(groupStores, key);\n        if (Array.isArray(state)) {\n          const newState = [...state];\n          newState.splice(index, 1, value);\n          setStoreValue(groupStores, key, newState);\n        } else {\n          setStoreValue(groupStores, key, state);\n        }\n      });\n      subscriptions.add(unsub);\n    }\n  }\n\n  function groupHasChanged(rows: Element[]) {\n    groupStores.formReady.set(false);\n    const currentVals = groupStores.formValues.get();\n    destroyGroup();\n    cleanupStores(rows);\n    for (let i = 0; i < rows.length; i++) {\n      const row = rows[i] as HTMLElement;\n      row.setAttribute('data-beaker-index', `${i}`);\n      const form = createForm(\n        {\n          ...formulaOptions,\n          defaultValues: defaultValues?.[i] || {},\n        },\n        undefined,\n        groupName,\n        currentVals[i] || {},\n      );\n      const instance = form.init(row);\n      formulaInstances.set(row, form);\n      formInstances.set(row, instance);\n      setupSubscriptions(form, i);\n    }\n    groupStores.formReady.set(true);\n  }\n\n  function setupGroupContainer(node: HTMLElement) {\n    globalObserver = new MutationObserver(() => {\n      const rows = node.querySelectorAll(':scope > *');\n      groupHasChanged(Array.from(rows));\n    });\n\n    globalObserver.observe(node, { childList: true });\n    const rows = node.querySelectorAll(':scope > *');\n    groupHasChanged(Array.from(rows));\n  }\n\n  return {\n    group: (node: HTMLElement) => {\n      if (node.id) {\n        groupName = node.id;\n        beakerStores.set(groupName, groupStores);\n      } else {\n        groupName = `beaker-group-${groupCounter++}`;\n        node.id = groupName;\n      }\n\n      node.setAttribute('data-beaker-group', 'true');\n      if (!node.hasAttribute('aria-role')) {\n        node.setAttribute('aria-role', 'group');\n      }\n      setupGroupContainer(node);\n\n      return {\n        destroy: () => {\n          if (groupName) {\n            beakerStores.delete(groupName);\n          }\n          destroyGroup();\n          globalObserver.disconnect();\n        },\n      };\n    },\n    update: (options: FormulaOptions) => {\n      formulaInstances.forEach((form) => form.updateForm(options));\n    },\n    destroy: () => {\n      if (groupName) {\n        beakerStores.delete(groupName);\n      }\n      destroyGroup();\n      globalObserver.disconnect();\n    },\n    forms: formulaInstances,\n    stores: groupStores,\n    init: (items: Array<Record<string, unknown>>) => groupStores.formValues.set(items),\n    add: (item: Record<string, unknown>) => groupStores.formValues.set([...groupStores.formValues.get(), item]),\n    set: (index: number, item: Record<string, unknown>) => {\n      const newState = [...groupStores.formValues.get()];\n      newState.splice(index, 1, item);\n      groupStores.formValues.set(newState);\n    },\n    delete: (index: number) =>\n      Object.keys(groupStores).forEach((key) => {\n        const state = getStoreValue(groupStores, key);\n        if (Array.isArray(state)) {\n          const newState = [...state];\n          newState.splice(index, 1);\n          setStoreValue(groupStores, key, newState);\n        }\n      }),\n    clear: () => groupStores.formValues.set([]),\n    ...groupStores,\n  };\n}\n"],"names":["getStoreValue","stores","key","setStoreValue","value","groupCounter","createGroup","options","beakerStores","groupStores","createGroupStores","groupName","globalObserver","defaultValues","formulaOptions","formulaInstances","formInstances","subscriptions","destroyGroup","instance","sub","cleanupStores","rows","state","setupSubscriptions","form","index","formStores","store","initial","unsub","newState","groupHasChanged","currentVals","i","row","createForm","setupGroupContainer","node","items","item"],"mappings":"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"}