{"version":3,"file":"notify.mjs","sources":["../../../../../../packages/components/notification/src/notify.ts"],"sourcesContent":["import { createVNode, render } from 'vue'\nimport { isClient } from '@vueuse/core'\nimport { useZIndex } from '@bigin/hooks'\nimport { debugWarn, isElement, isString, isVNode } from '@bigin/utils'\nimport NotificationConstructor from './notification.vue'\nimport { notificationTypes } from './notification'\n\nimport type { AppContext, Ref, VNode } from 'vue'\nimport type {\n  NotificationOptions,\n  NotificationProps,\n  NotificationQueue,\n  Notify,\n  NotifyFn,\n} from './notification'\n\n// This should be a queue but considering there were `non-autoclosable` notifications.\nconst notifications: Record<\n  NotificationOptions['position'],\n  NotificationQueue\n> = {\n  'top-left': [],\n  'top-right': [],\n  'bottom-left': [],\n  'bottom-right': [],\n}\n\n// the gap size between each notification\nconst GAP_SIZE = 16\nlet seed = 1\n\nconst notify: NotifyFn & Partial<Notify> & { _context: AppContext | null } =\n  function (options = {}, context: AppContext | null = null) {\n    if (!isClient) return { close: () => undefined }\n\n    if (typeof options === 'string' || isVNode(options)) {\n      options = { message: options }\n    }\n\n    const position = options.position || 'top-right'\n\n    let verticalOffset = options.offset || 0\n    notifications[position].forEach(({ vm }) => {\n      verticalOffset += (vm.el?.offsetHeight || 0) + GAP_SIZE\n    })\n    verticalOffset += GAP_SIZE\n\n    const { nextZIndex } = useZIndex()\n\n    const id = `notification_${seed++}`\n    const userOnClose = options.onClose\n    const props: Partial<NotificationProps> = {\n      ...options,\n      zIndex: nextZIndex(),\n      offset: verticalOffset,\n      id,\n      onClose: () => {\n        close(id, position, userOnClose)\n      },\n    }\n\n    let appendTo: HTMLElement | null = document.body\n    if (isElement(options.appendTo)) {\n      appendTo = options.appendTo\n    } else if (isString(options.appendTo)) {\n      appendTo = document.querySelector(options.appendTo)\n    }\n\n    // should fallback to default value with a warning\n    if (!isElement(appendTo)) {\n      debugWarn(\n        'BNotification',\n        'the appendTo option is not an HTMLElement. Falling back to document.body.'\n      )\n      appendTo = document.body\n    }\n\n    const container = document.createElement('div')\n\n    const vm = createVNode(\n      NotificationConstructor,\n      props,\n      isVNode(props.message)\n        ? {\n            default: () => props.message,\n          }\n        : null\n    )\n    vm.appContext = context ?? notify._context\n\n    // clean notification element preventing mem leak\n    vm.props!.onDestroy = () => {\n      render(null, container)\n    }\n\n    // instances will remove this item when close function gets called. So we do not need to worry about it.\n    render(vm, container)\n    notifications[position].push({ vm })\n    appendTo.appendChild(container.firstElementChild!)\n\n    return {\n      // instead of calling the onClose function directly, setting this value so that we can have the full lifecycle\n      // for out component, so that all closing steps will not be skipped.\n      close: () => {\n        ;(vm.component!.exposed as { visible: Ref<boolean> }).visible.value =\n          false\n      },\n    }\n  }\nnotificationTypes.forEach((type) => {\n  notify[type] = (options = {}) => {\n    if (typeof options === 'string' || isVNode(options)) {\n      options = {\n        message: options,\n      }\n    }\n    return notify({\n      ...options,\n      type,\n    })\n  }\n})\n\n/**\n * This function gets called when user click `x` button or press `esc` or the time reached its limitation.\n * Emitted by transition@before-leave event so that we can fetch the current notification.offsetHeight, if this was called\n * by @after-leave the DOM element will be removed from the page thus we can no longer fetch the offsetHeight.\n * @param {String} id notification id to be closed\n * @param {Position} position the positioning strategy\n * @param {Function} userOnClose the callback called when close passed by user\n */\nexport function close(\n  id: string,\n  position: NotificationOptions['position'],\n  userOnClose?: (vm: VNode) => void\n): void {\n  // maybe we can store the index when inserting the vm to notification list.\n  const orientedNotifications = notifications[position]\n  const idx = orientedNotifications.findIndex(\n    ({ vm }) => vm.component?.props.id === id\n  )\n  if (idx === -1) return\n  const { vm } = orientedNotifications[idx]\n  if (!vm) return\n  // calling user's on close function before notification gets removed from DOM.\n  userOnClose?.(vm)\n\n  // note that this is called @before-leave, that's why we were able to fetch this property.\n  const removedHeight = vm.el!.offsetHeight\n  const verticalPos = position.split('-')[0]\n  orientedNotifications.splice(idx, 1)\n  const len = orientedNotifications.length\n  if (len < 1) return\n  // starting from the removing item.\n  for (let i = idx; i < len; i++) {\n    // new position equals the current offsetTop minus removed height plus 16px(the gap size between each item)\n    const { el, component } = orientedNotifications[i].vm\n    const pos =\n      Number.parseInt(el!.style[verticalPos], 10) - removedHeight - GAP_SIZE\n    component!.props.offset = pos\n  }\n}\n\nexport function closeAll(): void {\n  // loop through all directions, close them at once.\n  for (const orientedNotifications of Object.values(notifications)) {\n    orientedNotifications.forEach(({ vm }) => {\n      // same as the previous close method, we'd like to make sure lifecycle gets handle properly.\n      ;(vm.component!.exposed as { visible: Ref<boolean> }).visible.value =\n        false\n    })\n  }\n}\n\nnotify.closeAll = closeAll\nnotify._context = null\n\nexport default notify as Notify\n"],"names":["vm"],"mappings":"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"}