threepipe
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

GridItemList.ts 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import {createDiv, createStyles, mobileAndTabletCheck} from 'ts-browser-helpers'
  2. import tippy from 'tippy.js'
  3. import tippyStyles from 'tippy.js/dist/tippy.css?inline'
  4. import styles from './GridItemList.css?inline'
  5. export interface GridItem {
  6. id: string
  7. image: string
  8. onClick?: (id: string) => void
  9. tooltip?: string
  10. }
  11. /**
  12. * Earlier it was called CustomContextGrid.
  13. * Used to create a overlay of grid items over the canvas allowing users to pick from a list of items.
  14. */
  15. export class GridItemList {
  16. public static Elements: HTMLDivElement[] = []
  17. // private static _inited = false
  18. private static _container = document.createElement('div')
  19. private static _initializeStyles(): void {
  20. // GridItemList._inited = true // since container is cleared
  21. createStyles(styles, GridItemList._container)
  22. createStyles(tippyStyles, GridItemList._container)
  23. GridItemList._container.id = 'gridItemList'
  24. GridItemList._container.style.position = 'absolute'
  25. GridItemList._container.style.top = '0'
  26. GridItemList._container.style.left = '0'
  27. GridItemList._container.style.width = '270px'
  28. GridItemList._container.style.height = '100%'
  29. GridItemList._container.style.pointerEvents = 'none'
  30. GridItemList._container.style.zIndex = '100'
  31. GridItemList._container.style.overflowY = 'auto'
  32. }
  33. public static Create<T extends GridItem>(tag: string, title: string, cols: number, x: number, y: number, items: T[], processDiv: (d: HTMLDivElement, item: T, container: HTMLElement) => void): HTMLDivElement {
  34. // if (!GridItemList._inited) GridItemList._initialize()
  35. const isMobile = mobileAndTabletCheck()
  36. const gap = isMobile ? 0.15 : 0.25 // rem
  37. const itemWidth = isMobile ? 1.5 : 2.5 // rem
  38. const margin = isMobile ? 1 : 1 // rem
  39. // if (GridItemList.Element) GridItemList.Remove()
  40. const container = createDiv({
  41. classList: ['customContextGrid'], addToBody: false,
  42. innerHTML: `
  43. <div class="customContextGridHeading"> ${title} </div>
  44. `,
  45. })
  46. container.style.top = y + 'px'
  47. container.style.left = x + 'px'
  48. container.style.gap = gap + 'rem'
  49. container.style.width = (itemWidth + gap) * cols - gap + margin + 'rem' // `calc(${100.0 / cols}%-${gap * cols}rem)`
  50. container.dataset.tag = tag
  51. for (const item of items) {
  52. const d = createDiv({
  53. classList: ['customContextGridItems'], addToBody: false, innerHTML: `
  54. <img src="${item.image}" class="customContextGridItemImage">
  55. `,
  56. })
  57. d.style.width = itemWidth + 'rem'
  58. d.style.height = itemWidth + 'rem'
  59. container.appendChild(d)
  60. d.onclick = () => item.onClick?.(item.id)
  61. if (item.tooltip) tippy(d, {placement: 'bottom', content: item.tooltip})
  62. processDiv(d, item, container)
  63. }
  64. GridItemList.Elements?.push(container)
  65. return container
  66. }
  67. public static RemoveAll(tag?: string): void {
  68. if (!tag) {
  69. for (const element of GridItemList.Elements) element.remove()
  70. GridItemList.Elements = []
  71. } else {
  72. const el = GridItemList.Elements.filter(e => e.dataset.tag === tag)
  73. for (const element of el) element.remove()
  74. GridItemList.Elements = GridItemList.Elements.filter(e => e.dataset.tag !== tag)
  75. }
  76. }
  77. public static RebuildUi(parent?: HTMLElement): void {
  78. if (GridItemList.Elements.length === 0) return
  79. if (!parent) parent = createDiv({addToBody: true, classList: ['customContextGridParent']})
  80. for (const element of GridItemList.Elements) element.remove()
  81. GridItemList._container.innerHTML = ''
  82. GridItemList._initializeStyles()
  83. let y = 20
  84. parent.appendChild(GridItemList._container)
  85. for (const element of GridItemList.Elements) {
  86. element.style.top = y + 'px'
  87. GridItemList._container.appendChild(element)
  88. y += element.clientHeight + 20
  89. }
  90. }
  91. public static Dispose() {
  92. GridItemList.RemoveAll()
  93. GridItemList._container.remove()
  94. GridItemList._container.innerHTML = ''
  95. }
  96. }