apex-grid 3.3.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/README.md +74 -6
  3. package/components/cell.d.ts +2 -2
  4. package/components/cell.js +30 -2
  5. package/components/cell.js.map +1 -1
  6. package/components/filter-row.js +65 -6
  7. package/components/filter-row.js.map +1 -1
  8. package/components/grid.d.ts +132 -0
  9. package/components/grid.js +59 -2
  10. package/components/grid.js.map +1 -1
  11. package/components/header-row.js +8 -0
  12. package/components/header-row.js.map +1 -1
  13. package/components/header.js +85 -12
  14. package/components/header.js.map +1 -1
  15. package/components/row.js +32 -4
  16. package/components/row.js.map +1 -1
  17. package/components/virtualizer.d.ts +5 -1
  18. package/components/virtualizer.js +72 -2
  19. package/components/virtualizer.js.map +1 -1
  20. package/controllers/expansion.js +4 -4
  21. package/controllers/expansion.js.map +1 -1
  22. package/controllers/filter.js +11 -0
  23. package/controllers/filter.js.map +1 -1
  24. package/controllers/history.js +11 -4
  25. package/controllers/history.js.map +1 -1
  26. package/controllers/navigation.d.ts +35 -2
  27. package/controllers/navigation.js +102 -8
  28. package/controllers/navigation.js.map +1 -1
  29. package/controllers/pagination.js +1 -1
  30. package/controllers/pagination.js.map +1 -1
  31. package/controllers/reorder.js +4 -2
  32. package/controllers/reorder.js.map +1 -1
  33. package/controllers/row-pin.js +2 -2
  34. package/controllers/row-pin.js.map +1 -1
  35. package/controllers/row-reorder.js +6 -6
  36. package/controllers/row-reorder.js.map +1 -1
  37. package/controllers/selection.js +3 -3
  38. package/controllers/selection.js.map +1 -1
  39. package/controllers/sort.js +4 -2
  40. package/controllers/sort.js.map +1 -1
  41. package/controllers/state.d.ts +9 -3
  42. package/controllers/state.js +11 -1
  43. package/controllers/state.js.map +1 -1
  44. package/custom-elements.json +664 -190
  45. package/docs/assets/hierarchy.js +1 -1
  46. package/docs/assets/navigation.js +1 -1
  47. package/docs/assets/search.js +1 -1
  48. package/docs/classes/ApexGrid.html +586 -0
  49. package/docs/classes/ApexGridPaginator.html +36 -0
  50. package/docs/classes/ApexGridToolbar.html +67 -0
  51. package/docs/functions/localize.html +2 -2
  52. package/docs/functions/setup.html +1 -2
  53. package/docs/hierarchy.html +1 -1
  54. package/docs/index.html +94 -6
  55. package/docs/interfaces/ApexCellValidationFailedEvent.html +1 -1
  56. package/docs/interfaces/ApexCellValueChangedEvent.html +1 -1
  57. package/docs/interfaces/ApexCellValueChangingEvent.html +2 -2
  58. package/docs/interfaces/ApexColumnMovedEvent.html +2 -2
  59. package/docs/interfaces/ApexColumnMovingEvent.html +1 -1
  60. package/docs/interfaces/ApexDetailContext.html +2 -2
  61. package/docs/interfaces/ApexGridEventMap.html +5 -5
  62. package/docs/interfaces/ApexRowMovingEvent.html +1 -1
  63. package/docs/interfaces/ApexRowPinningEvent.html +1 -1
  64. package/docs/interfaces/BaseApexCellContext.html +1 -1
  65. package/docs/interfaces/BaseApexEditorContext.html +1 -1
  66. package/docs/interfaces/BaseColumnConfiguration.html +3 -3
  67. package/docs/interfaces/CSVExportOptions.html +2 -2
  68. package/docs/interfaces/DataPipelineConfiguration.html +2 -2
  69. package/docs/interfaces/EditingHistoryConfiguration.html +1 -1
  70. package/docs/interfaces/ExportFormat.html +2 -2
  71. package/docs/interfaces/ExportOptions.html +1 -1
  72. package/docs/interfaces/GridRowPinningConfiguration.html +1 -1
  73. package/docs/interfaces/GridRowReorderingConfiguration.html +2 -2
  74. package/docs/interfaces/PaginationConfiguration.html +1 -1
  75. package/docs/interfaces/PaginationState.html +1 -1
  76. package/docs/media/_tokens.scss +29 -8
  77. package/docs/media/package.json +4 -5
  78. package/docs/media/state-persistence.html +0 -10
  79. package/docs/modules.html +1 -1
  80. package/docs/types/DataPipelineParams.html +2 -2
  81. package/docs/types/EditMode.html +2 -2
  82. package/docs/types/GridLocaleText.html +1 -1
  83. package/docs/types/PaginationMode.html +1 -1
  84. package/docs/variables/EN_LOCALE.html +3 -3
  85. package/docs/variables/esLocale.html +1 -1
  86. package/i18n/en.d.ts +109 -1
  87. package/i18n/en.js +109 -1
  88. package/i18n/en.js.map +1 -1
  89. package/i18n/es.js +109 -1
  90. package/i18n/es.js.map +1 -1
  91. package/index.d.ts +2 -0
  92. package/index.js +2 -0
  93. package/index.js.map +1 -1
  94. package/internal/column-types.js +1 -1
  95. package/internal/column-types.js.map +1 -1
  96. package/internal/feature-module.d.ts +22 -0
  97. package/internal/feature-module.js +5 -0
  98. package/internal/feature-module.js.map +1 -1
  99. package/internal/index.d.ts +2 -2
  100. package/internal/index.js +1 -1
  101. package/internal/index.js.map +1 -1
  102. package/internal/utils.d.ts +14 -0
  103. package/internal/utils.js +5 -0
  104. package/internal/utils.js.map +1 -1
  105. package/package.json +1 -2
  106. package/setup.d.ts +12 -11
  107. package/setup.js +12 -4
  108. package/setup.js.map +1 -1
  109. package/styles/_common.css.js +1 -1
  110. package/styles/_common.css.js.map +1 -1
  111. package/styles/_tokens.css.js +1 -1
  112. package/styles/_tokens.css.js.map +1 -1
  113. package/styles/body-cell/body-cell.css.js +1 -1
  114. package/styles/body-cell/body-cell.css.js.map +1 -1
  115. package/styles/body-row/body-row.css.js +1 -1
  116. package/styles/body-row/body-row.css.js.map +1 -1
  117. package/styles/filter-row/filter-row.css.js +1 -1
  118. package/styles/filter-row/filter-row.css.js.map +1 -1
  119. package/styles/grid/_grid.base.css.js +1 -1
  120. package/styles/grid/_grid.base.css.js.map +1 -1
  121. package/styles/grid/grid.css.js +1 -1
  122. package/styles/grid/grid.css.js.map +1 -1
  123. package/styles/group-header-row/group-header-row.css.js +1 -1
  124. package/styles/group-header-row/group-header-row.css.js.map +1 -1
  125. package/styles/header-cell/header-cell.css.js +1 -1
  126. package/styles/header-cell/header-cell.css.js.map +1 -1
  127. package/styles/header-row/header-row.base.css.js +1 -1
  128. package/styles/header-row/header-row.base.css.js.map +1 -1
  129. package/styles/paginator/paginator.css.js +1 -1
  130. package/styles/paginator/paginator.css.js.map +1 -1
  131. package/styles/toolbar/toolbar.css.js +1 -1
  132. package/styles/toolbar/toolbar.css.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"row-reorder.js","sourceRoot":"","sources":["../../src/controllers/row-reorder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAuB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAO5F,MAAM,iBAAiB,GAAG,CAAC,CAAC;AA+D5B,MAAM,OAAO,oBAAoB;IAE/B,MAAM,CAAoB;IAG1B,QAAQ,CAAoB;IAgB5B,SAAS,CAAS;IAOlB,QAAQ,CAMQ;IAEhB,YAAsB,IAAiB;QAAjB,SAAI,GAAJ,IAAI,CAAa;QAlCvC,WAAM,GAAe,IAAI,CAAC;QAG1B,aAAQ,GAAe,IAAI,CAAC;QAGrB,aAAQ,GAAa,IAAI,CAAC;QAO1B,UAAK,GAAyB,IAAI,CAAC;QAGnC,YAAO,GAAa,IAAI,CAAC;QAGhC,cAAS,GAAG,KAAK,CAAC;QAOlB,aAAQ,GAMG,IAAI,CAAC;QA6MhB,uBAAkB,GAAG,CAAC,KAAmB,EAAQ,EAAE;YACjD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC9B,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS;gBAAE,OAAO;YAC9D,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC1C,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,iBAAiB;oBAAE,OAAO;gBAGnD,IAAI,CAAC;oBACH,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBACzD,CAAC;gBAAC,MAAM,CAAC;gBAET,CAAC;gBACD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,qBAAgB,GAAG,CAAC,KAAmB,EAAQ,EAAE;YAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC9B,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS;gBAAE,OAAO;YAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;YAC/B,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACjE,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC7D,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACjE,IAAI,CAAC;gBACH,IAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC;oBAAE,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC/F,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC;QA5OA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAGD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,IAA8B,CAAC;IAC7C,CAAC;IAEM,aAAa,KAAI,CAAC;IAGzB,IAAW,OAAO;QAChB,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAOD,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,KAAK,KAAK,CAAC;IACnE,CAAC;IAMD,IAAW,gBAAgB;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAGD,IAAW,WAAW;QACpB,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACvD,CAAC;IAGD,IAAW,cAAc;QACvB,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC;IAC9B,CAAC;IAGD,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;IAC/B,CAAC;IAOM,KAAK,CAAC,IAAS;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAa,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YAC7B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC5E,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC5E,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAMM,cAAc;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAOM,kBAAkB,CAAC,KAAiB;QACzC,IAAI,CAAC,MAAM,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChD,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAKM,gBAAgB,CAAC,QAAQ,GAAG,KAAK;QACtC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC;IAC/D,CAAC;IASM,OAAO,CAAC,IAAY,EAAE,EAAU,EAAE,WAA4B,QAAQ;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAM,EAAE,IAAI,CAAC,EAAE,CAAM,EAAE,QAAQ,CAAC,CAAC;QAClE,IAAI,EAAE;YAAE,KAAK,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC3C,OAAO,EAAE,CAAC;IACZ,CAAC;IASM,SAAS,CAAC,MAAS,EAAE,KAAoB;QAC9C,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK;YAChB,CAAC,CAAC;gBACE,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;gBAClB,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG;gBACjB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK;gBACvB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;gBACzB,cAAc,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI;gBAC/C,cAAc,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG;gBAC9C,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB;YACH,CAAC,CAAC,IAAI,CAAC;QACT,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAGM,SAAS,CAAC,OAAe,EAAE,OAAe;QAC/C,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QACxB,IAAI,CAAC,KAAK,GAAG;YACX,GAAG,IAAI,CAAC,KAAK;YACb,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc;YACtC,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc;SACvC,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAMM,QAAQ,CAAC,OAAe;QAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ;YAAE,OAAO;QAErD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,SAAS,KAAK,CAAC,CAAC;YAAE,OAAO;QAEjD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5C,IAAI,QAAyB,CAAC;QAC9B,IAAI,SAAS,GAAG,SAAS,EAAE,CAAC;YAC1B,IAAI,OAAO,GAAG,QAAQ;gBAAE,OAAO;YAC/B,QAAQ,GAAG,OAAO,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,IAAI,OAAO,GAAG,QAAQ;gBAAE,OAAO;YAC/B,QAAQ,GAAG,QAAQ,CAAC;QACtB,CAAC;QACD,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAGM,OAAO;QACZ,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAUM,cAAc,CAAC,IAAO,EAAE,QAA4B,EAAE,KAAmB;QAC9E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO;QACvF,IAAI,CAAC,QAAQ,GAAG;YACd,IAAI;YACJ,QAAQ;YACR,MAAM,EAAE,KAAK,CAAC,OAAO;YACrB,MAAM,EAAE,KAAK,CAAC,OAAO;YACrB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;QAC/B,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC9D,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC1D,IAAI,CAAC,gBAAgB,CAAC,eAAe,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChE,CAAC;IAED,kBAAkB,CAkBhB;IAEF,gBAAgB,CAcd;IAEF,KAAK,CAAC,SAAS,CAAC,MAAS,EAAE,QAAyB;QAClD,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;gBAC/B,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAKM,IAAI,CAAC,QAAgB;QAC1B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAkB,CAAC;QAC3D,IAAI,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,uEAAuE,CAAC,CAAC;QAC5F,OAAO,IAAI,CAAC;IACd,CAAC;IAMM,WAAW,CAAC,SAAiB;QAClC,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;QACnC,IAAI,OAAO,KAAK,CAAC,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAM,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;YAC3F,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;QACH,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,CAAC;QACnB,KAAK,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,yBAAyB,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1D,OAAO,MAAM,CAAC;IAChB,CAAC;IAGM,IAAI;QACT,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;IAGM,UAAU;QACf,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IAC1C,CAAC;IASD,OAAO,CACL,MAAqB,EACrB,MAAqB,EACrB,QAAyB,EACzB,UAAgC,EAAE;QAElC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,MAAM;YAAE,OAAO,KAAK,CAAC;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;YAC/C,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YAClC,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAE3B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,GAAI,IAAI,CAAC,IAAI,CAAC,QAA6B,CAAC,CAAC;QAC9E,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;QACtD,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/B,IAAI,QAAQ,KAAK,OAAO;YAAE,KAAK,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QAE9B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,WAAW,CAAC,KAAuB;QACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAa,CAAC;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACvB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,IAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACpC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC5E,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC5E,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAGD,UAAU,CAAC,OAAe;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QACpC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAChF,MAAM,OAAO,GAAG,GAA6B,CAAC;YAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;YAC7C,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM;gBAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;QACvF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gBAAgB;QACd,MAAM,OAAO,GAAwB,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,EAAE,GAAG,GAA6B,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,MAAwC;QAC7D,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;QAC/B,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,YAAY,CAAC,MAAwC;QACnD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAA6B,CAAC,CAAC;QACtD,CAAC;QACD,aAAa,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;IACjE,CAAC;CACF","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { PIPELINE } from '../internal/constants.js';\nimport { awaitChildUpdates, type KeyedFlipEntry, playKeyedFlip } from '../internal/flip.js';\nimport type { GridHost } from '../internal/types.js';\n\n/** Where a moved row lands relative to its target. */\nexport type RowDropPosition = 'before' | 'after';\n\n/** Pixels the pointer must travel before a row drag engages. */\nconst DRAG_THRESHOLD_PX = 4;\n\n/** A single cell snapshot used to paint the floating row ghost. */\nexport interface RowGhostCell {\n /** The cell's rendered text at grab time. */\n text: string;\n /** The cell's rendered width (px), so the ghost matches the column layout. */\n width: number;\n /** The cell's computed `text-align`, so numbers stay right-aligned in the ghost. */\n align: string;\n}\n\n/** Everything the row hands the controller to seed the floating ghost. */\nexport interface RowGhostInit {\n /** The source row's bounding rect at grab time. */\n rect: DOMRect;\n /** Pointer position at grab time (to keep the grab point under the cursor). */\n clientX: number;\n clientY: number;\n /** Per-cell snapshot of the row's visible content. */\n cells: RowGhostCell[];\n}\n\n/**\n * Live state for the floating \"ghost\" row that trails the cursor during a\n * pointer drag. Mirrors {@link ReorderController}'s column ghost: the source\n * row stays in the grid (and live-swaps), the ghost is a purely visual proxy.\n */\nexport interface RowGhostState {\n /** Ghost position (viewport-relative top-left, in CSS pixels). */\n x: number;\n y: number;\n /** Ghost size, fixed at the source row's initial bounding rect. */\n width: number;\n height: number;\n /** Cursor offset within the ghost so the grab point stays under the cursor. */\n pointerOffsetX: number;\n pointerOffsetY: number;\n /** Snapshot of the row's visible cells. */\n cells: ReadonlyArray<RowGhostCell>;\n}\n\n/**\n * Reactive controller backing row drag-reorder and a manual row order.\n *\n * @remarks\n * Row order is normally derived (filter → sort). This controller adds a\n * **manual order**: an explicit sequence of row references applied as a\n * pipeline step after sort. While a manual order is active, sorting is mutually\n * exclusive (applying a sort clears the manual order). State is reference-based,\n * so it survives the in-place pipeline.\n *\n * Reordering happens through {@link moveRow} (pointer live-swap during a drag,\n * the keyboard grab/move flow, or the public API). Each move goes through the\n * cancellable `rowMoving` event and emits a follow-up `rowMoved`, then animates\n * with a Y-axis FLIP. Pinned rows (F4) are never the drag source and reorder\n * only within the unpinned body set.\n *\n * Persistence: by default the order lives in this controller and the app\n * persists via `rowMoved`. With `rowReordering.applyToData` the move also\n * splices {@link ApexGrid.data} in place (and clears the manual order, since the\n * data array then carries the order).\n */\nexport class RowReorderController<T extends object> implements ReactiveController {\n /** Manual order of row references, or `null` for the natural (sorted) order. */\n #order: T[] | null = null;\n\n /** Order snapshot captured at keyboard-grab time, for Escape-to-cancel. */\n #preGrab: T[] | null = null;\n\n /** The row currently being pointer-dragged, or `null`. */\n public dragging: T | null = null;\n\n /**\n * Live floating-ghost state during a pointer drag, or `null`. Surfaced to the\n * grid, which renders the ghost at the top of its shadow tree (outside the\n * virtualizer) so `position: fixed` tracks the viewport cleanly.\n */\n public ghost: RowGhostState | null = null;\n\n /** The row currently grabbed for keyboard reorder, or `null`. */\n public grabbed: T | null = null;\n\n /** Re-entrancy guard so a slow swap can't trigger a second mid-drag. */\n #swapping = false;\n\n /**\n * In-flight pointer-drag gesture. The move/up listeners live on the **grid\n * host** (a stable element), not the row, so a live-swap that recycles the\n * source row's DOM can't tear the drag down mid-gesture.\n */\n #pending: {\n data: T;\n getGhost: () => RowGhostInit;\n startX: number;\n startY: number;\n pointerId: number;\n } | null = null;\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n /** The grid host as a DOM event target (it is always an `HTMLElement`). */\n get #hostElement(): HTMLElement {\n return this.host as unknown as HTMLElement;\n }\n\n public hostConnected() {}\n\n /** Whether row reordering is enabled at the grid level. */\n public get enabled(): boolean {\n return Boolean(this.host.rowReordering?.enabled);\n }\n\n /**\n * Whether a pointer drag must start from the dedicated grip handle (the\n * default), rather than from anywhere on the row. Driven by\n * `rowReordering.handle` (defaults to `true`).\n */\n public get handleMode(): boolean {\n return this.enabled && this.host.rowReordering?.handle !== false;\n }\n\n /**\n * Whether the leading grip-handle column is rendered. Only in handle mode, and\n * only while reordering is enabled.\n */\n public get showHandleColumn(): boolean {\n return this.handleMode;\n }\n\n /** Whether moves also splice {@link ApexGrid.data} in place. */\n public get applyToData(): boolean {\n return Boolean(this.host.rowReordering?.applyToData);\n }\n\n /** Whether a manual order is currently active. */\n public get hasManualOrder(): boolean {\n return this.#order !== null;\n }\n\n /** Whether a row is currently grabbed for keyboard reorder. */\n public get isGrabbing(): boolean {\n return this.grabbed !== null;\n }\n\n /**\n * Pipeline step: reorders the (post-filter, post-sort) rows by the manual\n * order. Rows absent from the manual order (e.g. newly added) keep their\n * incoming relative order at the end. Identity pass-through when inactive.\n */\n public apply(rows: T[]): T[] {\n if (!this.#order) return rows;\n const rank = new Map<T, number>();\n this.#order.forEach((row, i) => {\n rank.set(row, i);\n });\n return [...rows].sort((a, b) => {\n const ra = rank.has(a) ? (rank.get(a) as number) : Number.POSITIVE_INFINITY;\n const rb = rank.has(b) ? (rank.get(b) as number) : Number.POSITIVE_INFINITY;\n return ra - rb;\n });\n }\n\n /**\n * The current manual order as a copy of its row references, or `null` for the\n * derived order. Consumed by `ApexGrid.getState`.\n */\n public getManualOrder(): T[] | null {\n return this.#order ? [...this.#order] : null;\n }\n\n /**\n * Restores a manual order from a list of row references (state restore). Pass\n * `null` (or an empty list) to clear it. Silent: emits no `rowMoving` /\n * `rowMoved` and does not animate; re-runs the pipeline.\n */\n public restoreManualOrder(order: T[] | null): void {\n this.#order = order?.length ? [...order] : null;\n this.host.requestUpdate(PIPELINE);\n }\n\n /**\n * Clears the manual order (e.g. when a sort is applied). Re-runs the pipeline.\n */\n public clearManualOrder(announce = false): void {\n if (!this.#order) return;\n this.#order = null;\n this.host.requestUpdate(PIPELINE);\n if (announce) this.host.announce('Manual row order cleared');\n }\n\n /**\n * Moves the row at view index `from` relative to the row at view index `to`.\n * Indices are into {@link ApexGrid.pageItems}.\n *\n * @returns `true` when applied, `false` when disabled, out of range, or\n * cancelled via `rowMoving`.\n */\n public moveRow(from: number, to: number, position: RowDropPosition = 'before'): boolean {\n const view = this.host.pageItems;\n const before = this.#captureRowRects();\n const ok = this.#commit(view[from] as T, view[to] as T, position);\n if (ok) void this.#flipAfterUpdate(before);\n return ok;\n }\n\n // --- pointer drag -------------------------------------------------------\n\n /**\n * Begins a pointer drag from `source`. When `ghost` is supplied (the pointer\n * path always does), seeds the floating ghost from the source row's rect and\n * the grab point so it stays anchored under the cursor.\n */\n public startDrag(source: T, ghost?: RowGhostInit): void {\n if (!this.enabled) return;\n this.dragging = source;\n this.ghost = ghost\n ? {\n x: ghost.rect.left,\n y: ghost.rect.top,\n width: ghost.rect.width,\n height: ghost.rect.height,\n pointerOffsetX: ghost.clientX - ghost.rect.left,\n pointerOffsetY: ghost.clientY - ghost.rect.top,\n cells: ghost.cells,\n }\n : null;\n this.host.requestUpdate();\n }\n\n /** Moves the floating ghost to track the cursor. No-op without an active ghost. */\n public moveGhost(clientX: number, clientY: number): void {\n if (!this.ghost) return;\n this.ghost = {\n ...this.ghost,\n x: clientX - this.ghost.pointerOffsetX,\n y: clientY - this.ghost.pointerOffsetY,\n };\n this.host.requestUpdate();\n }\n\n /**\n * Called on pointer-move during a drag: live-swaps the dragged row past the\n * body row currently under `clientY` once the cursor crosses its midpoint.\n */\n public dragOver(clientY: number): void {\n if (!this.dragging || this.#swapping) return;\n const target = this.#bodyRowAt(clientY);\n if (!target || target.data === this.dragging) return;\n\n const view = this.host.pageItems;\n const sourceIdx = view.indexOf(this.dragging);\n const targetIdx = view.indexOf(target.data);\n if (sourceIdx === -1 || targetIdx === -1) return;\n\n const rect = target.element.getBoundingClientRect();\n const midpoint = rect.top + rect.height / 2;\n let position: RowDropPosition;\n if (sourceIdx < targetIdx) {\n if (clientY < midpoint) return; // dragging down — wait for the midpoint\n position = 'after';\n } else {\n if (clientY > midpoint) return; // dragging up\n position = 'before';\n }\n void this.#dragSwap(target.data, position);\n }\n\n /** Ends the pointer drag. The order is already final (live-swapped). */\n public endDrag(): void {\n if (!this.dragging) return;\n this.dragging = null;\n this.ghost = null;\n this.host.requestUpdate();\n }\n\n /**\n * Arms a pointer drag from a row press. Called by the row on `pointerdown`\n * (from the grip in handle mode, or anywhere in whole-row mode). The move /\n * up / cancel listeners are bound to the **grid host**, so the gesture is\n * immune to the source row's DOM being recycled by a live-swap. `getGhost` is\n * a thunk the controller invokes once, the instant the drag engages, to\n * snapshot the row's cells (the row is still in place then).\n */\n public armPointerDrag(data: T, getGhost: () => RowGhostInit, event: PointerEvent): void {\n const pinned = this.host.pinnedRows;\n if (!this.enabled || pinned.top.includes(data) || pinned.bottom.includes(data)) return;\n this.#pending = {\n data,\n getGhost,\n startX: event.clientX,\n startY: event.clientY,\n pointerId: event.pointerId,\n };\n const host = this.#hostElement;\n host.addEventListener('pointermove', this.#onHostPointerMove);\n host.addEventListener('pointerup', this.#onHostPointerUp);\n host.addEventListener('pointercancel', this.#onHostPointerUp);\n }\n\n #onHostPointerMove = (event: PointerEvent): void => {\n const pending = this.#pending;\n if (!pending || event.pointerId !== pending.pointerId) return;\n if (!this.dragging) {\n const dx = event.clientX - pending.startX;\n const dy = event.clientY - pending.startY;\n if (Math.hypot(dx, dy) < DRAG_THRESHOLD_PX) return;\n // Capture on the stable host so moves keep arriving even when the cursor\n // leaves the grid, and so the source row reflowing can't drop the pointer.\n try {\n this.#hostElement.setPointerCapture(pending.pointerId);\n } catch {\n /* a synthetic pointer id may not be capturable; hit-testing still works */\n }\n this.startDrag(pending.data, pending.getGhost());\n }\n this.moveGhost(event.clientX, event.clientY);\n this.dragOver(event.clientY);\n };\n\n #onHostPointerUp = (event: PointerEvent): void => {\n const pending = this.#pending;\n if (!pending || event.pointerId !== pending.pointerId) return;\n const host = this.#hostElement;\n host.removeEventListener('pointermove', this.#onHostPointerMove);\n host.removeEventListener('pointerup', this.#onHostPointerUp);\n host.removeEventListener('pointercancel', this.#onHostPointerUp);\n try {\n if (host.hasPointerCapture(pending.pointerId)) host.releasePointerCapture(pending.pointerId);\n } catch {\n /* capture was never taken or already released */\n }\n this.#pending = null;\n this.endDrag();\n };\n\n async #dragSwap(target: T, position: RowDropPosition): Promise<void> {\n if (this.#swapping) return;\n this.#swapping = true;\n try {\n const before = this.#captureRowRects();\n if (this.#commit(this.dragging as T, target, position)) {\n await this.host.updateComplete;\n await awaitChildUpdates(this.host.rows);\n this.#playRowFlip(before);\n }\n } finally {\n this.#swapping = false;\n }\n }\n\n // --- keyboard grab ------------------------------------------------------\n\n /** Grabs the row at view index `rowIndex` for keyboard reorder. */\n public grab(rowIndex: number): boolean {\n if (!this.enabled) return false;\n const row = this.host.pageItems[rowIndex] as T | undefined;\n if (!row) return false;\n this.grabbed = row;\n this.#preGrab = this.#order ? [...this.#order] : null;\n this.host.requestUpdate();\n this.host.announce('Row grabbed. Use arrow keys to move, Enter to drop, Escape to cancel.');\n return true;\n }\n\n /**\n * Moves the grabbed row one position in `direction`. Returns the grabbed\n * row's new view index, or `-1` when it can't move (no grab / at the edge).\n */\n public moveGrabbed(direction: -1 | 1): number {\n if (!this.grabbed) return -1;\n const view = this.host.pageItems;\n const current = view.indexOf(this.grabbed);\n const target = current + direction;\n if (current === -1 || target < 0 || target >= view.length) return -1;\n const before = this.#captureRowRects();\n const ok = this.#commit(this.grabbed, view[target] as T, direction > 0 ? 'after' : 'before', {\n silent: true,\n });\n if (!ok) return -1;\n void this.#flipAfterUpdate(before);\n this.host.announce(`Row moved to position ${target + 1}`);\n return target;\n }\n\n /** Drops the grabbed row, keeping its moves. */\n public drop(): void {\n if (!this.grabbed) return;\n this.grabbed = null;\n this.#preGrab = null;\n this.host.requestUpdate();\n this.host.announce('Row dropped');\n }\n\n /** Cancels the grab, reverting to the order captured when it was grabbed. */\n public cancelGrab(): void {\n if (!this.grabbed) return;\n this.grabbed = null;\n this.#order = this.#preGrab;\n this.#preGrab = null;\n this.host.requestUpdate(PIPELINE);\n this.host.announce('Reorder cancelled');\n }\n\n // --- internals ----------------------------------------------------------\n\n /**\n * The core order mutation: validates, emits `rowMoving` (cancellable),\n * updates the manual order (or splices data when `applyToData`), re-runs the\n * pipeline, and emits `rowMoved`. Does not animate.\n */\n #commit(\n source: T | undefined,\n target: T | undefined,\n position: RowDropPosition,\n options: { silent?: boolean } = {}\n ): boolean {\n if (!this.enabled || !source || !target || source === target) return false;\n const view = this.host.pageItems;\n const from = view.indexOf(source);\n const to = view.indexOf(target);\n\n const proceed = this.host.emitEvent('rowMoving', {\n detail: { from, to, data: source },\n cancelable: true,\n });\n if (!proceed) return false;\n\n const baseline = this.#order ?? [...(this.host.dataView as ReadonlyArray<T>)];\n const next = baseline.filter((row) => row !== source);\n let index = next.indexOf(target);\n if (index === -1) return false;\n if (position === 'after') index += 1;\n next.splice(index, 0, source);\n\n if (this.applyToData) {\n this.#spliceData(next);\n this.#order = null; // the data array now carries the order\n } else {\n this.#order = next;\n }\n\n this.host.requestUpdate(PIPELINE);\n if (!options.silent) this.host.announce('Row moved');\n this.host.emitEvent('rowMoved', { detail: { from, to, data: source } });\n return true;\n }\n\n /** Reorders {@link ApexGrid.data} in place to match `order`. */\n #spliceData(order: ReadonlyArray<T>): void {\n const rank = new Map<T, number>();\n order.forEach((row, i) => {\n rank.set(row, i);\n });\n (this.host.data as T[]).sort((a, b) => {\n const ra = rank.has(a) ? (rank.get(a) as number) : Number.POSITIVE_INFINITY;\n const rb = rank.has(b) ? (rank.get(b) as number) : Number.POSITIVE_INFINITY;\n return ra - rb;\n });\n }\n\n /** The rendered body row (non-pinned) whose box contains `clientY`. */\n #bodyRowAt(clientY: number): { data: T; element: HTMLElement } | null {\n const pinned = this.host.pinnedRows;\n for (const row of this.host.rows) {\n if (pinned.top.includes(row.data) || pinned.bottom.includes(row.data)) continue;\n const element = row as unknown as HTMLElement;\n const rect = element.getBoundingClientRect();\n if (clientY >= rect.top && clientY < rect.bottom) return { data: row.data, element };\n }\n return null;\n }\n\n #captureRowRects(): KeyedFlipEntry<T>[] {\n const entries: KeyedFlipEntry<T>[] = [];\n for (const row of this.host.rows) {\n const el = row as unknown as HTMLElement;\n entries.push({ key: row.data, rect: el.getBoundingClientRect() });\n }\n return entries;\n }\n\n async #flipAfterUpdate(before: ReadonlyArray<KeyedFlipEntry<T>>): Promise<void> {\n await this.host.updateComplete;\n await awaitChildUpdates(this.host.rows);\n this.#playRowFlip(before);\n }\n\n #playRowFlip(before: ReadonlyArray<KeyedFlipEntry<T>>): void {\n const byData = new Map<T, HTMLElement>();\n for (const row of this.host.rows) {\n byData.set(row.data, row as unknown as HTMLElement);\n }\n playKeyedFlip(before, (data) => byData.get(data) ?? null, 'y');\n }\n}\n"]}
1
+ {"version":3,"file":"row-reorder.js","sourceRoot":"","sources":["../../src/controllers/row-reorder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAuB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAO5F,MAAM,iBAAiB,GAAG,CAAC,CAAC;AA+D5B,MAAM,OAAO,oBAAoB;IAE/B,MAAM,CAAoB;IAG1B,QAAQ,CAAoB;IAgB5B,SAAS,CAAS;IAOlB,QAAQ,CAMQ;IAEhB,YAAsB,IAAiB;QAAjB,SAAI,GAAJ,IAAI,CAAa;QAlCvC,WAAM,GAAe,IAAI,CAAC;QAG1B,aAAQ,GAAe,IAAI,CAAC;QAGrB,aAAQ,GAAa,IAAI,CAAC;QAO1B,UAAK,GAAyB,IAAI,CAAC;QAGnC,YAAO,GAAa,IAAI,CAAC;QAGhC,cAAS,GAAG,KAAK,CAAC;QAOlB,aAAQ,GAMG,IAAI,CAAC;QA6MhB,uBAAkB,GAAG,CAAC,KAAmB,EAAQ,EAAE;YACjD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC9B,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS;gBAAE,OAAO;YAC9D,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC1C,MAAM,EAAE,GAAG,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;gBAC1C,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,iBAAiB;oBAAE,OAAO;gBAGnD,IAAI,CAAC;oBACH,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBACzD,CAAC;gBAAC,MAAM,CAAC;gBAET,CAAC;gBACD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,qBAAgB,GAAG,CAAC,KAAmB,EAAQ,EAAE;YAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC9B,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO,CAAC,SAAS;gBAAE,OAAO;YAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;YAC/B,IAAI,CAAC,mBAAmB,CAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACjE,IAAI,CAAC,mBAAmB,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC7D,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACjE,IAAI,CAAC;gBACH,IAAI,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC;oBAAE,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC/F,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,CAAC;QA5OA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAGD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,IAA8B,CAAC;IAC7C,CAAC;IAEM,aAAa,KAAI,CAAC;IAGzB,IAAW,OAAO;QAChB,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAOD,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,KAAK,KAAK,CAAC;IACnE,CAAC;IAMD,IAAW,gBAAgB;QACzB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAGD,IAAW,WAAW;QACpB,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACvD,CAAC;IAGD,IAAW,cAAc;QACvB,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC;IAC9B,CAAC;IAGD,IAAW,UAAU;QACnB,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;IAC/B,CAAC;IAOM,KAAK,CAAC,IAAS;QACpB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAa,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YAC7B,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC5E,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC5E,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAMM,cAAc;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC;IAOM,kBAAkB,CAAC,KAAiB;QACzC,IAAI,CAAC,MAAM,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChD,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAKM,gBAAgB,CAAC,QAAQ,GAAG,KAAK;QACtC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACtF,CAAC;IASM,OAAO,CAAC,IAAY,EAAE,EAAU,EAAE,WAA4B,QAAQ;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAM,EAAE,IAAI,CAAC,EAAE,CAAM,EAAE,QAAQ,CAAC,CAAC;QAClE,IAAI,EAAE;YAAE,KAAK,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC3C,OAAO,EAAE,CAAC;IACZ,CAAC;IASM,SAAS,CAAC,MAAS,EAAE,KAAoB;QAC9C,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK;YAChB,CAAC,CAAC;gBACE,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI;gBAClB,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG;gBACjB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK;gBACvB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM;gBACzB,cAAc,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI;gBAC/C,cAAc,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG;gBAC9C,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB;YACH,CAAC,CAAC,IAAI,CAAC;QACT,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAGM,SAAS,CAAC,OAAe,EAAE,OAAe;QAC/C,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO;QACxB,IAAI,CAAC,KAAK,GAAG;YACX,GAAG,IAAI,CAAC,KAAK;YACb,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc;YACtC,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc;SACvC,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAMM,QAAQ,CAAC,OAAe;QAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,QAAQ;YAAE,OAAO;QAErD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,SAAS,KAAK,CAAC,CAAC;YAAE,OAAO;QAEjD,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5C,IAAI,QAAyB,CAAC;QAC9B,IAAI,SAAS,GAAG,SAAS,EAAE,CAAC;YAC1B,IAAI,OAAO,GAAG,QAAQ;gBAAE,OAAO;YAC/B,QAAQ,GAAG,OAAO,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,IAAI,OAAO,GAAG,QAAQ;gBAAE,OAAO;YAC/B,QAAQ,GAAG,QAAQ,CAAC;QACtB,CAAC;QACD,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IAGM,OAAO;QACZ,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC3B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAUM,cAAc,CAAC,IAAO,EAAE,QAA4B,EAAE,KAAmB;QAC9E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO;QACvF,IAAI,CAAC,QAAQ,GAAG;YACd,IAAI;YACJ,QAAQ;YACR,MAAM,EAAE,KAAK,CAAC,OAAO;YACrB,MAAM,EAAE,KAAK,CAAC,OAAO;YACrB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;QAC/B,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC9D,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC1D,IAAI,CAAC,gBAAgB,CAAC,eAAe,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAChE,CAAC;IAED,kBAAkB,CAkBhB;IAEF,gBAAgB,CAcd;IAEF,KAAK,CAAC,SAAS,CAAC,MAAS,EAAE,QAAyB;QAClD,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAa,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACvD,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;gBAC/B,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAKM,IAAI,CAAC,QAAgB;QAC1B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAkB,CAAC;QAC3D,IAAI,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IAMM,WAAW,CAAC,SAAiB;QAClC,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;QACnC,IAAI,OAAO,KAAK,CAAC,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,MAAM,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAM,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;YAC3F,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;QACH,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,CAAC;QACnB,KAAK,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QACxF,OAAO,MAAM,CAAC;IAChB,CAAC;IAGM,IAAI;QACT,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAChE,CAAC;IAGM,UAAU;QACf,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACtE,CAAC;IASD,OAAO,CACL,MAAqB,EACrB,MAAqB,EACrB,QAAyB,EACzB,UAAgC,EAAE;QAElC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI,MAAM,KAAK,MAAM;YAAE,OAAO,KAAK,CAAC;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;YAC/C,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;YAClC,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAE3B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,GAAI,IAAI,CAAC,IAAI,CAAC,QAA6B,CAAC,CAAC;QAC9E,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC;QACtD,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/B,IAAI,QAAQ,KAAK,OAAO;YAAE,KAAK,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QAE9B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACrB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACjF,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAGD,WAAW,CAAC,KAAuB;QACjC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAa,CAAC;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACvB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,IAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACpC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC5E,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAY,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;YAC5E,OAAO,EAAE,GAAG,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAGD,UAAU,CAAC,OAAe;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QACpC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAChF,MAAM,OAAO,GAAG,GAA6B,CAAC;YAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC;YAC7C,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM;gBAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;QACvF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gBAAgB;QACd,MAAM,OAAO,GAAwB,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,EAAE,GAAG,GAA6B,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,MAAwC;QAC7D,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC;QAC/B,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,YAAY,CAAC,MAAwC;QACnD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAA6B,CAAC,CAAC;QACtD,CAAC;QACD,aAAa,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;IACjE,CAAC;CACF","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { PIPELINE } from '../internal/constants.js';\nimport { awaitChildUpdates, type KeyedFlipEntry, playKeyedFlip } from '../internal/flip.js';\nimport type { GridHost } from '../internal/types.js';\n\n/** Where a moved row lands relative to its target. */\nexport type RowDropPosition = 'before' | 'after';\n\n/** Pixels the pointer must travel before a row drag engages. */\nconst DRAG_THRESHOLD_PX = 4;\n\n/** A single cell snapshot used to paint the floating row ghost. */\nexport interface RowGhostCell {\n /** The cell's rendered text at grab time. */\n text: string;\n /** The cell's rendered width (px), so the ghost matches the column layout. */\n width: number;\n /** The cell's computed `text-align`, so numbers stay right-aligned in the ghost. */\n align: string;\n}\n\n/** Everything the row hands the controller to seed the floating ghost. */\nexport interface RowGhostInit {\n /** The source row's bounding rect at grab time. */\n rect: DOMRect;\n /** Pointer position at grab time (to keep the grab point under the cursor). */\n clientX: number;\n clientY: number;\n /** Per-cell snapshot of the row's visible content. */\n cells: RowGhostCell[];\n}\n\n/**\n * Live state for the floating \"ghost\" row that trails the cursor during a\n * pointer drag. Mirrors {@link ReorderController}'s column ghost: the source\n * row stays in the grid (and live-swaps), the ghost is a purely visual proxy.\n */\nexport interface RowGhostState {\n /** Ghost position (viewport-relative top-left, in CSS pixels). */\n x: number;\n y: number;\n /** Ghost size, fixed at the source row's initial bounding rect. */\n width: number;\n height: number;\n /** Cursor offset within the ghost so the grab point stays under the cursor. */\n pointerOffsetX: number;\n pointerOffsetY: number;\n /** Snapshot of the row's visible cells. */\n cells: ReadonlyArray<RowGhostCell>;\n}\n\n/**\n * Reactive controller backing row drag-reorder and a manual row order.\n *\n * @remarks\n * Row order is normally derived (filter → sort). This controller adds a\n * **manual order**: an explicit sequence of row references applied as a\n * pipeline step after sort. While a manual order is active, sorting is mutually\n * exclusive (applying a sort clears the manual order). State is reference-based,\n * so it survives the in-place pipeline.\n *\n * Reordering happens through {@link moveRow} (pointer live-swap during a drag,\n * the keyboard grab/move flow, or the public API). Each move goes through the\n * cancellable `rowMoving` event and emits a follow-up `rowMoved`, then animates\n * with a Y-axis FLIP. Pinned rows (F4) are never the drag source and reorder\n * only within the unpinned body set.\n *\n * Persistence: by default the order lives in this controller and the app\n * persists via `rowMoved`. With `rowReordering.applyToData` the move also\n * splices {@link ApexGrid.data} in place (and clears the manual order, since the\n * data array then carries the order).\n */\nexport class RowReorderController<T extends object> implements ReactiveController {\n /** Manual order of row references, or `null` for the natural (sorted) order. */\n #order: T[] | null = null;\n\n /** Order snapshot captured at keyboard-grab time, for Escape-to-cancel. */\n #preGrab: T[] | null = null;\n\n /** The row currently being pointer-dragged, or `null`. */\n public dragging: T | null = null;\n\n /**\n * Live floating-ghost state during a pointer drag, or `null`. Surfaced to the\n * grid, which renders the ghost at the top of its shadow tree (outside the\n * virtualizer) so `position: fixed` tracks the viewport cleanly.\n */\n public ghost: RowGhostState | null = null;\n\n /** The row currently grabbed for keyboard reorder, or `null`. */\n public grabbed: T | null = null;\n\n /** Re-entrancy guard so a slow swap can't trigger a second mid-drag. */\n #swapping = false;\n\n /**\n * In-flight pointer-drag gesture. The move/up listeners live on the **grid\n * host** (a stable element), not the row, so a live-swap that recycles the\n * source row's DOM can't tear the drag down mid-gesture.\n */\n #pending: {\n data: T;\n getGhost: () => RowGhostInit;\n startX: number;\n startY: number;\n pointerId: number;\n } | null = null;\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n /** The grid host as a DOM event target (it is always an `HTMLElement`). */\n get #hostElement(): HTMLElement {\n return this.host as unknown as HTMLElement;\n }\n\n public hostConnected() {}\n\n /** Whether row reordering is enabled at the grid level. */\n public get enabled(): boolean {\n return Boolean(this.host.rowReordering?.enabled);\n }\n\n /**\n * Whether a pointer drag must start from the dedicated grip handle (the\n * default), rather than from anywhere on the row. Driven by\n * `rowReordering.handle` (defaults to `true`).\n */\n public get handleMode(): boolean {\n return this.enabled && this.host.rowReordering?.handle !== false;\n }\n\n /**\n * Whether the leading grip-handle column is rendered. Only in handle mode, and\n * only while reordering is enabled.\n */\n public get showHandleColumn(): boolean {\n return this.handleMode;\n }\n\n /** Whether moves also splice {@link ApexGrid.data} in place. */\n public get applyToData(): boolean {\n return Boolean(this.host.rowReordering?.applyToData);\n }\n\n /** Whether a manual order is currently active. */\n public get hasManualOrder(): boolean {\n return this.#order !== null;\n }\n\n /** Whether a row is currently grabbed for keyboard reorder. */\n public get isGrabbing(): boolean {\n return this.grabbed !== null;\n }\n\n /**\n * Pipeline step: reorders the (post-filter, post-sort) rows by the manual\n * order. Rows absent from the manual order (e.g. newly added) keep their\n * incoming relative order at the end. Identity pass-through when inactive.\n */\n public apply(rows: T[]): T[] {\n if (!this.#order) return rows;\n const rank = new Map<T, number>();\n this.#order.forEach((row, i) => {\n rank.set(row, i);\n });\n return [...rows].sort((a, b) => {\n const ra = rank.has(a) ? (rank.get(a) as number) : Number.POSITIVE_INFINITY;\n const rb = rank.has(b) ? (rank.get(b) as number) : Number.POSITIVE_INFINITY;\n return ra - rb;\n });\n }\n\n /**\n * The current manual order as a copy of its row references, or `null` for the\n * derived order. Consumed by `ApexGrid.getState`.\n */\n public getManualOrder(): T[] | null {\n return this.#order ? [...this.#order] : null;\n }\n\n /**\n * Restores a manual order from a list of row references (state restore). Pass\n * `null` (or an empty list) to clear it. Silent: emits no `rowMoving` /\n * `rowMoved` and does not animate; re-runs the pipeline.\n */\n public restoreManualOrder(order: T[] | null): void {\n this.#order = order?.length ? [...order] : null;\n this.host.requestUpdate(PIPELINE);\n }\n\n /**\n * Clears the manual order (e.g. when a sort is applied). Re-runs the pipeline.\n */\n public clearManualOrder(announce = false): void {\n if (!this.#order) return;\n this.#order = null;\n this.host.requestUpdate(PIPELINE);\n if (announce) this.host.announce(this.host.localize('announce.manualOrderCleared'));\n }\n\n /**\n * Moves the row at view index `from` relative to the row at view index `to`.\n * Indices are into {@link ApexGrid.pageItems}.\n *\n * @returns `true` when applied, `false` when disabled, out of range, or\n * cancelled via `rowMoving`.\n */\n public moveRow(from: number, to: number, position: RowDropPosition = 'before'): boolean {\n const view = this.host.pageItems;\n const before = this.#captureRowRects();\n const ok = this.#commit(view[from] as T, view[to] as T, position);\n if (ok) void this.#flipAfterUpdate(before);\n return ok;\n }\n\n // --- pointer drag -------------------------------------------------------\n\n /**\n * Begins a pointer drag from `source`. When `ghost` is supplied (the pointer\n * path always does), seeds the floating ghost from the source row's rect and\n * the grab point so it stays anchored under the cursor.\n */\n public startDrag(source: T, ghost?: RowGhostInit): void {\n if (!this.enabled) return;\n this.dragging = source;\n this.ghost = ghost\n ? {\n x: ghost.rect.left,\n y: ghost.rect.top,\n width: ghost.rect.width,\n height: ghost.rect.height,\n pointerOffsetX: ghost.clientX - ghost.rect.left,\n pointerOffsetY: ghost.clientY - ghost.rect.top,\n cells: ghost.cells,\n }\n : null;\n this.host.requestUpdate();\n }\n\n /** Moves the floating ghost to track the cursor. No-op without an active ghost. */\n public moveGhost(clientX: number, clientY: number): void {\n if (!this.ghost) return;\n this.ghost = {\n ...this.ghost,\n x: clientX - this.ghost.pointerOffsetX,\n y: clientY - this.ghost.pointerOffsetY,\n };\n this.host.requestUpdate();\n }\n\n /**\n * Called on pointer-move during a drag: live-swaps the dragged row past the\n * body row currently under `clientY` once the cursor crosses its midpoint.\n */\n public dragOver(clientY: number): void {\n if (!this.dragging || this.#swapping) return;\n const target = this.#bodyRowAt(clientY);\n if (!target || target.data === this.dragging) return;\n\n const view = this.host.pageItems;\n const sourceIdx = view.indexOf(this.dragging);\n const targetIdx = view.indexOf(target.data);\n if (sourceIdx === -1 || targetIdx === -1) return;\n\n const rect = target.element.getBoundingClientRect();\n const midpoint = rect.top + rect.height / 2;\n let position: RowDropPosition;\n if (sourceIdx < targetIdx) {\n if (clientY < midpoint) return; // dragging down — wait for the midpoint\n position = 'after';\n } else {\n if (clientY > midpoint) return; // dragging up\n position = 'before';\n }\n void this.#dragSwap(target.data, position);\n }\n\n /** Ends the pointer drag. The order is already final (live-swapped). */\n public endDrag(): void {\n if (!this.dragging) return;\n this.dragging = null;\n this.ghost = null;\n this.host.requestUpdate();\n }\n\n /**\n * Arms a pointer drag from a row press. Called by the row on `pointerdown`\n * (from the grip in handle mode, or anywhere in whole-row mode). The move /\n * up / cancel listeners are bound to the **grid host**, so the gesture is\n * immune to the source row's DOM being recycled by a live-swap. `getGhost` is\n * a thunk the controller invokes once, the instant the drag engages, to\n * snapshot the row's cells (the row is still in place then).\n */\n public armPointerDrag(data: T, getGhost: () => RowGhostInit, event: PointerEvent): void {\n const pinned = this.host.pinnedRows;\n if (!this.enabled || pinned.top.includes(data) || pinned.bottom.includes(data)) return;\n this.#pending = {\n data,\n getGhost,\n startX: event.clientX,\n startY: event.clientY,\n pointerId: event.pointerId,\n };\n const host = this.#hostElement;\n host.addEventListener('pointermove', this.#onHostPointerMove);\n host.addEventListener('pointerup', this.#onHostPointerUp);\n host.addEventListener('pointercancel', this.#onHostPointerUp);\n }\n\n #onHostPointerMove = (event: PointerEvent): void => {\n const pending = this.#pending;\n if (!pending || event.pointerId !== pending.pointerId) return;\n if (!this.dragging) {\n const dx = event.clientX - pending.startX;\n const dy = event.clientY - pending.startY;\n if (Math.hypot(dx, dy) < DRAG_THRESHOLD_PX) return;\n // Capture on the stable host so moves keep arriving even when the cursor\n // leaves the grid, and so the source row reflowing can't drop the pointer.\n try {\n this.#hostElement.setPointerCapture(pending.pointerId);\n } catch {\n /* a synthetic pointer id may not be capturable; hit-testing still works */\n }\n this.startDrag(pending.data, pending.getGhost());\n }\n this.moveGhost(event.clientX, event.clientY);\n this.dragOver(event.clientY);\n };\n\n #onHostPointerUp = (event: PointerEvent): void => {\n const pending = this.#pending;\n if (!pending || event.pointerId !== pending.pointerId) return;\n const host = this.#hostElement;\n host.removeEventListener('pointermove', this.#onHostPointerMove);\n host.removeEventListener('pointerup', this.#onHostPointerUp);\n host.removeEventListener('pointercancel', this.#onHostPointerUp);\n try {\n if (host.hasPointerCapture(pending.pointerId)) host.releasePointerCapture(pending.pointerId);\n } catch {\n /* capture was never taken or already released */\n }\n this.#pending = null;\n this.endDrag();\n };\n\n async #dragSwap(target: T, position: RowDropPosition): Promise<void> {\n if (this.#swapping) return;\n this.#swapping = true;\n try {\n const before = this.#captureRowRects();\n if (this.#commit(this.dragging as T, target, position)) {\n await this.host.updateComplete;\n await awaitChildUpdates(this.host.rows);\n this.#playRowFlip(before);\n }\n } finally {\n this.#swapping = false;\n }\n }\n\n // --- keyboard grab ------------------------------------------------------\n\n /** Grabs the row at view index `rowIndex` for keyboard reorder. */\n public grab(rowIndex: number): boolean {\n if (!this.enabled) return false;\n const row = this.host.pageItems[rowIndex] as T | undefined;\n if (!row) return false;\n this.grabbed = row;\n this.#preGrab = this.#order ? [...this.#order] : null;\n this.host.requestUpdate();\n this.host.announce(this.host.localize('announce.rowGrabbed'));\n return true;\n }\n\n /**\n * Moves the grabbed row one position in `direction`. Returns the grabbed\n * row's new view index, or `-1` when it can't move (no grab / at the edge).\n */\n public moveGrabbed(direction: -1 | 1): number {\n if (!this.grabbed) return -1;\n const view = this.host.pageItems;\n const current = view.indexOf(this.grabbed);\n const target = current + direction;\n if (current === -1 || target < 0 || target >= view.length) return -1;\n const before = this.#captureRowRects();\n const ok = this.#commit(this.grabbed, view[target] as T, direction > 0 ? 'after' : 'before', {\n silent: true,\n });\n if (!ok) return -1;\n void this.#flipAfterUpdate(before);\n this.host.announce(this.host.localize('announce.rowMovedTo', { position: target + 1 }));\n return target;\n }\n\n /** Drops the grabbed row, keeping its moves. */\n public drop(): void {\n if (!this.grabbed) return;\n this.grabbed = null;\n this.#preGrab = null;\n this.host.requestUpdate();\n this.host.announce(this.host.localize('announce.rowDropped'));\n }\n\n /** Cancels the grab, reverting to the order captured when it was grabbed. */\n public cancelGrab(): void {\n if (!this.grabbed) return;\n this.grabbed = null;\n this.#order = this.#preGrab;\n this.#preGrab = null;\n this.host.requestUpdate(PIPELINE);\n this.host.announce(this.host.localize('announce.reorderCancelled'));\n }\n\n // --- internals ----------------------------------------------------------\n\n /**\n * The core order mutation: validates, emits `rowMoving` (cancellable),\n * updates the manual order (or splices data when `applyToData`), re-runs the\n * pipeline, and emits `rowMoved`. Does not animate.\n */\n #commit(\n source: T | undefined,\n target: T | undefined,\n position: RowDropPosition,\n options: { silent?: boolean } = {}\n ): boolean {\n if (!this.enabled || !source || !target || source === target) return false;\n const view = this.host.pageItems;\n const from = view.indexOf(source);\n const to = view.indexOf(target);\n\n const proceed = this.host.emitEvent('rowMoving', {\n detail: { from, to, data: source },\n cancelable: true,\n });\n if (!proceed) return false;\n\n const baseline = this.#order ?? [...(this.host.dataView as ReadonlyArray<T>)];\n const next = baseline.filter((row) => row !== source);\n let index = next.indexOf(target);\n if (index === -1) return false;\n if (position === 'after') index += 1;\n next.splice(index, 0, source);\n\n if (this.applyToData) {\n this.#spliceData(next);\n this.#order = null; // the data array now carries the order\n } else {\n this.#order = next;\n }\n\n this.host.requestUpdate(PIPELINE);\n if (!options.silent) this.host.announce(this.host.localize('announce.rowMoved'));\n this.host.emitEvent('rowMoved', { detail: { from, to, data: source } });\n return true;\n }\n\n /** Reorders {@link ApexGrid.data} in place to match `order`. */\n #spliceData(order: ReadonlyArray<T>): void {\n const rank = new Map<T, number>();\n order.forEach((row, i) => {\n rank.set(row, i);\n });\n (this.host.data as T[]).sort((a, b) => {\n const ra = rank.has(a) ? (rank.get(a) as number) : Number.POSITIVE_INFINITY;\n const rb = rank.has(b) ? (rank.get(b) as number) : Number.POSITIVE_INFINITY;\n return ra - rb;\n });\n }\n\n /** The rendered body row (non-pinned) whose box contains `clientY`. */\n #bodyRowAt(clientY: number): { data: T; element: HTMLElement } | null {\n const pinned = this.host.pinnedRows;\n for (const row of this.host.rows) {\n if (pinned.top.includes(row.data) || pinned.bottom.includes(row.data)) continue;\n const element = row as unknown as HTMLElement;\n const rect = element.getBoundingClientRect();\n if (clientY >= rect.top && clientY < rect.bottom) return { data: row.data, element };\n }\n return null;\n }\n\n #captureRowRects(): KeyedFlipEntry<T>[] {\n const entries: KeyedFlipEntry<T>[] = [];\n for (const row of this.host.rows) {\n const el = row as unknown as HTMLElement;\n entries.push({ key: row.data, rect: el.getBoundingClientRect() });\n }\n return entries;\n }\n\n async #flipAfterUpdate(before: ReadonlyArray<KeyedFlipEntry<T>>): Promise<void> {\n await this.host.updateComplete;\n await awaitChildUpdates(this.host.rows);\n this.#playRowFlip(before);\n }\n\n #playRowFlip(before: ReadonlyArray<KeyedFlipEntry<T>>): void {\n const byData = new Map<T, HTMLElement>();\n for (const row of this.host.rows) {\n byData.set(row.data, row as unknown as HTMLElement);\n }\n playKeyedFlip(before, (data) => byData.get(data) ?? null, 'y');\n }\n}\n"]}
@@ -151,13 +151,13 @@ export class SelectionController {
151
151
  this.host.requestUpdate();
152
152
  const total = this.selected.size;
153
153
  if (total === 0) {
154
- this.host.announce('Selection cleared');
154
+ this.host.announce(this.host.localize('announce.selectionCleared'));
155
155
  }
156
156
  else if (added.length === 1 && removed.length === 0 && total === 1) {
157
- this.host.announce('1 row selected');
157
+ this.host.announce(this.host.localize('announce.rowSelected'));
158
158
  }
159
159
  else {
160
- this.host.announce(`${total} rows selected`);
160
+ this.host.announce(this.host.localize('announce.rowsSelected', { count: total }));
161
161
  }
162
162
  this.host.emitEvent('rowSelected', {
163
163
  detail: { added, removed, selected: Array.from(this.selected) },
@@ -1 +1 @@
1
- {"version":3,"file":"selection.js","sourceRoot":"","sources":["../../src/controllers/selection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type { GridHost, SelectionMode } from '../internal/types.js';\n\n/**\n * The default selection configuration used when the grid has none set.\n */\nexport const DEFAULT_SELECTION_CONFIG = Object.freeze({\n enabled: false,\n mode: 'multiple' as SelectionMode,\n showCheckboxColumn: false,\n});\n\n/**\n * Reactive controller backing row selection.\n *\n * @remarks\n * Selection state is reference-based — the controller holds a `Set` of row\n * data references so the selection survives sort / filter / pagination as\n * long as those operations preserve identities (the default in-place\n * pipeline does). Replacing {@link ApexGrid.data} wholesale will invalidate\n * any selected rows that are no longer present in the new array; consumers\n * should call {@link clear} or re-apply selection after such a change.\n *\n * Mutations go through the cancellable `rowSelecting` event and emit a\n * follow-up `rowSelected` event, mirroring the pattern used by editing.\n */\nexport class SelectionController<T extends object> implements ReactiveController {\n /** Set of currently selected row data references. */\n public selected: Set<T> = new Set();\n\n /**\n * Anchor row for Shift+click range selection. Set whenever a single row\n * is toggled / picked so a follow-up Shift+click knows where to start.\n */\n public anchor: T | null = null;\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public hostConnected() {}\n\n /**\n * Whether selection is enabled at the grid level.\n */\n public get enabled(): boolean {\n return Boolean(this.host.selection?.enabled);\n }\n\n /**\n * The resolved selection mode (`'multiple'` if unset).\n */\n public get mode(): SelectionMode {\n return this.host.selection?.mode ?? DEFAULT_SELECTION_CONFIG.mode;\n }\n\n /**\n * Whether to render the built-in checkbox column.\n */\n public get showCheckboxColumn(): boolean {\n return (\n this.enabled &&\n (this.host.selection?.showCheckboxColumn ?? DEFAULT_SELECTION_CONFIG.showCheckboxColumn)\n );\n }\n\n /**\n * Whether the given row is currently selected.\n */\n public isSelected(row: T): boolean {\n return this.selected.has(row);\n }\n\n /**\n * Returns the currently selected rows in insertion order.\n */\n public selectedRows(): T[] {\n return Array.from(this.selected);\n }\n\n /**\n * Whether every row in the current view ({@link ApexGrid.dataView}) is\n * selected. Used by the header checkbox to render its \"all\" state.\n */\n public allSelected(): boolean {\n const view = this.host.dataView;\n if (view.length === 0) return false;\n return view.every((row) => this.selected.has(row as T));\n }\n\n /**\n * Whether some — but not all — rows in the current view are selected.\n * Used to render the header checkbox in its indeterminate state.\n */\n public someSelected(): boolean {\n if (this.selected.size === 0) return false;\n if (this.allSelected()) return false;\n return true;\n }\n\n /**\n * Toggles selection of `row`. In `'single'` mode this either selects the\n * row (replacing any previous selection) or deselects it if it was the\n * only selected row.\n */\n public async toggleRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n const next = new Set(this.selected);\n if (next.has(row)) {\n next.delete(row);\n } else {\n if (this.mode === 'single') next.clear();\n next.add(row);\n }\n this.anchor = next.has(row) ? row : null;\n return this.#commit(next);\n }\n\n /**\n * Adds `row` to the selection. In `'single'` mode the existing selection\n * is cleared first.\n */\n public async selectRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n const next = new Set(this.mode === 'single' ? [] : this.selected);\n next.add(row);\n this.anchor = row;\n return this.#commit(next);\n }\n\n /**\n * Removes `row` from the selection.\n */\n public async deselectRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (!this.selected.has(row)) return true;\n const next = new Set(this.selected);\n next.delete(row);\n return this.#commit(next);\n }\n\n /**\n * Adds `row` to the selection without affecting other selected rows\n * (`'multiple'` mode only). In `'single'` mode this behaves like\n * {@link selectRow}.\n */\n public async additiveToggle(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (this.mode === 'single') return this.toggleRow(row);\n const next = new Set(this.selected);\n if (next.has(row)) {\n next.delete(row);\n } else {\n next.add(row);\n }\n this.anchor = next.has(row) ? row : this.anchor;\n return this.#commit(next);\n }\n\n /**\n * Selects every row between {@link anchor} and `row` (inclusive) in the\n * current page view. No-op in `'single'` mode or when no anchor is set —\n * in those cases the call falls back to a plain {@link selectRow}.\n */\n public async rangeToggle(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (this.mode === 'single' || !this.anchor) {\n return this.selectRow(row);\n }\n const pageItems = this.host.pageItems as ReadonlyArray<T>;\n const startIdx = pageItems.indexOf(this.anchor);\n const endIdx = pageItems.indexOf(row);\n if (startIdx === -1 || endIdx === -1) {\n return this.selectRow(row);\n }\n const [lo, hi] = startIdx < endIdx ? [startIdx, endIdx] : [endIdx, startIdx];\n const next = new Set(this.selected);\n for (let i = lo; i <= hi; i++) {\n next.add(pageItems[i] as T);\n }\n return this.#commit(next);\n }\n\n /**\n * Selects every row currently in view ({@link ApexGrid.dataView}). No-op\n * in `'single'` mode.\n */\n public async selectAll(): Promise<boolean> {\n if (!this.enabled || this.mode === 'single') return false;\n const next = new Set(this.host.dataView as ReadonlyArray<T>);\n return this.#commit(next);\n }\n\n /**\n * Clears the selection.\n */\n public async clear(): Promise<boolean> {\n if (this.selected.size === 0) return true;\n return this.#commit(new Set());\n }\n\n /**\n * Replaces the current selection with `rows`. Used by the public\n * {@link ApexGrid.selectedRows} setter so callers can drive selection\n * programmatically. Single-mode keeps at most one row.\n */\n public async replaceSelection(rows: ReadonlyArray<T>): Promise<boolean> {\n if (!this.enabled) return false;\n const next = new Set(this.mode === 'single' ? rows.slice(0, 1) : rows);\n return this.#commit(next);\n }\n\n async #commit(next: Set<T>): Promise<boolean> {\n const added: T[] = [];\n const removed: T[] = [];\n for (const row of next) {\n if (!this.selected.has(row)) added.push(row);\n }\n for (const row of this.selected) {\n if (!next.has(row)) removed.push(row);\n }\n if (added.length === 0 && removed.length === 0) return true;\n\n const proceed = this.host.emitEvent('rowSelecting', {\n detail: {\n added,\n removed,\n current: Array.from(this.selected),\n next: Array.from(next),\n },\n cancelable: true,\n });\n if (!proceed) return false;\n\n this.selected = next;\n this.host.requestUpdate();\n\n const total = this.selected.size;\n if (total === 0) {\n this.host.announce('Selection cleared');\n } else if (added.length === 1 && removed.length === 0 && total === 1) {\n this.host.announce('1 row selected');\n } else {\n this.host.announce(`${total} rows selected`);\n }\n\n this.host.emitEvent('rowSelected', {\n detail: { added, removed, selected: Array.from(this.selected) },\n });\n return true;\n }\n}\n"]}
1
+ {"version":3,"file":"selection.js","sourceRoot":"","sources":["../../src/controllers/selection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport type { GridHost, SelectionMode } from '../internal/types.js';\n\n/**\n * The default selection configuration used when the grid has none set.\n */\nexport const DEFAULT_SELECTION_CONFIG = Object.freeze({\n enabled: false,\n mode: 'multiple' as SelectionMode,\n showCheckboxColumn: false,\n});\n\n/**\n * Reactive controller backing row selection.\n *\n * @remarks\n * Selection state is reference-based — the controller holds a `Set` of row\n * data references so the selection survives sort / filter / pagination as\n * long as those operations preserve identities (the default in-place\n * pipeline does). Replacing {@link ApexGrid.data} wholesale will invalidate\n * any selected rows that are no longer present in the new array; consumers\n * should call {@link clear} or re-apply selection after such a change.\n *\n * Mutations go through the cancellable `rowSelecting` event and emit a\n * follow-up `rowSelected` event, mirroring the pattern used by editing.\n */\nexport class SelectionController<T extends object> implements ReactiveController {\n /** Set of currently selected row data references. */\n public selected: Set<T> = new Set();\n\n /**\n * Anchor row for Shift+click range selection. Set whenever a single row\n * is toggled / picked so a follow-up Shift+click knows where to start.\n */\n public anchor: T | null = null;\n\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public hostConnected() {}\n\n /**\n * Whether selection is enabled at the grid level.\n */\n public get enabled(): boolean {\n return Boolean(this.host.selection?.enabled);\n }\n\n /**\n * The resolved selection mode (`'multiple'` if unset).\n */\n public get mode(): SelectionMode {\n return this.host.selection?.mode ?? DEFAULT_SELECTION_CONFIG.mode;\n }\n\n /**\n * Whether to render the built-in checkbox column.\n */\n public get showCheckboxColumn(): boolean {\n return (\n this.enabled &&\n (this.host.selection?.showCheckboxColumn ?? DEFAULT_SELECTION_CONFIG.showCheckboxColumn)\n );\n }\n\n /**\n * Whether the given row is currently selected.\n */\n public isSelected(row: T): boolean {\n return this.selected.has(row);\n }\n\n /**\n * Returns the currently selected rows in insertion order.\n */\n public selectedRows(): T[] {\n return Array.from(this.selected);\n }\n\n /**\n * Whether every row in the current view ({@link ApexGrid.dataView}) is\n * selected. Used by the header checkbox to render its \"all\" state.\n */\n public allSelected(): boolean {\n const view = this.host.dataView;\n if (view.length === 0) return false;\n return view.every((row) => this.selected.has(row as T));\n }\n\n /**\n * Whether some — but not all — rows in the current view are selected.\n * Used to render the header checkbox in its indeterminate state.\n */\n public someSelected(): boolean {\n if (this.selected.size === 0) return false;\n if (this.allSelected()) return false;\n return true;\n }\n\n /**\n * Toggles selection of `row`. In `'single'` mode this either selects the\n * row (replacing any previous selection) or deselects it if it was the\n * only selected row.\n */\n public async toggleRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n const next = new Set(this.selected);\n if (next.has(row)) {\n next.delete(row);\n } else {\n if (this.mode === 'single') next.clear();\n next.add(row);\n }\n this.anchor = next.has(row) ? row : null;\n return this.#commit(next);\n }\n\n /**\n * Adds `row` to the selection. In `'single'` mode the existing selection\n * is cleared first.\n */\n public async selectRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n const next = new Set(this.mode === 'single' ? [] : this.selected);\n next.add(row);\n this.anchor = row;\n return this.#commit(next);\n }\n\n /**\n * Removes `row` from the selection.\n */\n public async deselectRow(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (!this.selected.has(row)) return true;\n const next = new Set(this.selected);\n next.delete(row);\n return this.#commit(next);\n }\n\n /**\n * Adds `row` to the selection without affecting other selected rows\n * (`'multiple'` mode only). In `'single'` mode this behaves like\n * {@link selectRow}.\n */\n public async additiveToggle(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (this.mode === 'single') return this.toggleRow(row);\n const next = new Set(this.selected);\n if (next.has(row)) {\n next.delete(row);\n } else {\n next.add(row);\n }\n this.anchor = next.has(row) ? row : this.anchor;\n return this.#commit(next);\n }\n\n /**\n * Selects every row between {@link anchor} and `row` (inclusive) in the\n * current page view. No-op in `'single'` mode or when no anchor is set —\n * in those cases the call falls back to a plain {@link selectRow}.\n */\n public async rangeToggle(row: T): Promise<boolean> {\n if (!this.enabled) return false;\n if (this.mode === 'single' || !this.anchor) {\n return this.selectRow(row);\n }\n const pageItems = this.host.pageItems as ReadonlyArray<T>;\n const startIdx = pageItems.indexOf(this.anchor);\n const endIdx = pageItems.indexOf(row);\n if (startIdx === -1 || endIdx === -1) {\n return this.selectRow(row);\n }\n const [lo, hi] = startIdx < endIdx ? [startIdx, endIdx] : [endIdx, startIdx];\n const next = new Set(this.selected);\n for (let i = lo; i <= hi; i++) {\n next.add(pageItems[i] as T);\n }\n return this.#commit(next);\n }\n\n /**\n * Selects every row currently in view ({@link ApexGrid.dataView}). No-op\n * in `'single'` mode.\n */\n public async selectAll(): Promise<boolean> {\n if (!this.enabled || this.mode === 'single') return false;\n const next = new Set(this.host.dataView as ReadonlyArray<T>);\n return this.#commit(next);\n }\n\n /**\n * Clears the selection.\n */\n public async clear(): Promise<boolean> {\n if (this.selected.size === 0) return true;\n return this.#commit(new Set());\n }\n\n /**\n * Replaces the current selection with `rows`. Used by the public\n * {@link ApexGrid.selectedRows} setter so callers can drive selection\n * programmatically. Single-mode keeps at most one row.\n */\n public async replaceSelection(rows: ReadonlyArray<T>): Promise<boolean> {\n if (!this.enabled) return false;\n const next = new Set(this.mode === 'single' ? rows.slice(0, 1) : rows);\n return this.#commit(next);\n }\n\n async #commit(next: Set<T>): Promise<boolean> {\n const added: T[] = [];\n const removed: T[] = [];\n for (const row of next) {\n if (!this.selected.has(row)) added.push(row);\n }\n for (const row of this.selected) {\n if (!next.has(row)) removed.push(row);\n }\n if (added.length === 0 && removed.length === 0) return true;\n\n const proceed = this.host.emitEvent('rowSelecting', {\n detail: {\n added,\n removed,\n current: Array.from(this.selected),\n next: Array.from(next),\n },\n cancelable: true,\n });\n if (!proceed) return false;\n\n this.selected = next;\n this.host.requestUpdate();\n\n const total = this.selected.size;\n if (total === 0) {\n this.host.announce(this.host.localize('announce.selectionCleared'));\n } else if (added.length === 1 && removed.length === 0 && total === 1) {\n this.host.announce(this.host.localize('announce.rowSelected'));\n } else {\n this.host.announce(this.host.localize('announce.rowsSelected', { count: total }));\n }\n\n this.host.emitEvent('rowSelected', {\n detail: { added, removed, selected: Array.from(this.selected) },\n });\n return true;\n }\n}\n"]}
@@ -75,8 +75,10 @@ export class SortController {
75
75
  #announce(expression, column) {
76
76
  const label = column.headerText ?? String(column.key);
77
77
  const message = expression.direction === 'none'
78
- ? `Sort cleared on ${label}`
79
- : `Sorted by ${label} ${expression.direction}`;
78
+ ? this.host.localize('announce.sortCleared', { label })
79
+ : this.host.localize(expression.direction === 'ascending'
80
+ ? 'announce.sortedAscending'
81
+ : 'announce.sortedDescending', { label });
80
82
  this.host.announce(message);
81
83
  }
82
84
  #captureRowRects() {
@@ -1 +1 @@
1
- {"version":3,"file":"sort.js","sourceRoot":"","sources":["../../src/controllers/sort.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { PIPELINE } from '../internal/constants.js';\nimport { awaitChildUpdates, type KeyedFlipEntry, playKeyedFlip } from '../internal/flip.js';\nimport type {\n ColumnConfiguration,\n ColumnSortConfiguration,\n GridHost,\n Keys,\n} from '../internal/types.js';\nimport { asArray } from '../internal/utils.js';\nimport type { SortExpression, SortingDirection, SortState } from '../operations/sort/types.js';\n\nexport class SortController<T extends object> implements ReactiveController {\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public state: SortState<T> = new Map();\n\n get #isMultipleSort() {\n return this.host.sortConfiguration.multiple;\n }\n\n get #isTriStateSort() {\n return this.host.sortConfiguration.triState;\n }\n\n #resolveSortOptions(options?: boolean | ColumnSortConfiguration<T>) {\n const expr: Pick<SortExpression<T>, 'caseSensitive' | 'comparer'> = {\n caseSensitive: false,\n comparer: undefined,\n };\n\n if (!options || typeof options === 'boolean') {\n return expr as Partial<SortExpression<T>>;\n }\n\n return Object.assign(expr, {\n caseSensitive: options.caseSensitive,\n comparer: options.comparer,\n }) as Partial<SortExpression<T>>;\n }\n\n #createDefaultExpression(key: Keys<T>) {\n const options = this.host.getColumn(key)?.sort;\n\n return {\n key,\n direction: 'ascending',\n ...this.#resolveSortOptions(options),\n } as SortExpression<T>;\n }\n\n #orderBy(dir?: SortingDirection): SortingDirection {\n return this.#isTriStateSort\n ? dir === 'ascending'\n ? 'descending'\n : dir === 'descending'\n ? 'none'\n : 'ascending'\n : dir === 'ascending'\n ? 'descending'\n : 'ascending';\n }\n\n #emitSortingEvent(detail: SortExpression<T>) {\n return this.host.emitEvent('sorting', { detail, cancelable: true });\n }\n\n #emitSortedEvent(detail: SortExpression<T>) {\n return this.host.emitEvent('sorted', { detail });\n }\n\n #setExpression(expression: SortExpression<T>) {\n expression.direction === 'none'\n ? this.reset(expression.key)\n : this.state.set(expression.key, { ...expression });\n }\n\n public async sortFromHeaderClick(column: ColumnConfiguration<T>, additive = false) {\n const expression = this.prepareExpression(column);\n\n if (!this.#emitSortingEvent(expression)) {\n return;\n }\n\n // A plain click sorts by this column alone, clearing any other sorted\n // columns. Only a Ctrl/Cmd+click while multi-sort is enabled keeps the\n // existing sort keys and appends this column as an additional, lower-\n // priority sort. Without this gate every plain click would accumulate a\n // key, so a second column added behind a unique primary column would not\n // change the visible order at all.\n if (!this.#isMultipleSort || !additive) {\n this.reset();\n }\n\n // Capture visible-row rects keyed by data identity BEFORE the pipeline\n // runs. After the new render the virtualizer will have repositioned\n // rows; we use those captured rects as the \"First\" of a FLIP and\n // animate each row from its old viewport position back to identity.\n const beforeRects = this.#captureRowRects();\n\n this._sort(expression);\n\n await this.host.updateComplete;\n // Wait for body row updates so the new data is committed to each row\n // element before measuring the \"Last\" rect — otherwise the captured-\n // before and measured-after rects match and the animation no-ops.\n await awaitChildUpdates(this.host.rows);\n this.#playRowFlip(beforeRects);\n this.#announce(expression, column);\n this.#emitSortedEvent(expression);\n }\n\n #announce(expression: SortExpression<T>, column: ColumnConfiguration<T>) {\n const label = column.headerText ?? String(column.key);\n const message =\n expression.direction === 'none'\n ? `Sort cleared on ${label}`\n : `Sorted by ${label} ${expression.direction}`;\n this.host.announce(message);\n }\n\n #captureRowRects(): KeyedFlipEntry<T>[] {\n const entries: KeyedFlipEntry<T>[] = [];\n for (const row of this.host.rows) {\n const el = row as unknown as HTMLElement;\n entries.push({ key: row.data, rect: el.getBoundingClientRect() });\n }\n return entries;\n }\n\n #playRowFlip(before: ReadonlyArray<KeyedFlipEntry<T>>) {\n // After sort, the same data may be rendered by a different `<apex-grid-row>`\n // DOM element (virtualizer recycles rows). Resolve by data identity.\n const rows = this.host.rows;\n const byData = new Map<T, HTMLElement>();\n for (const row of rows) {\n byData.set(row.data, row as unknown as HTMLElement);\n }\n playKeyedFlip(before, (data) => byData.get(data) ?? null, 'y');\n }\n\n public prepareExpression({ key, sort: options }: ColumnConfiguration<T>): SortExpression<T> {\n if (this.state.has(key)) {\n const expr = this.state.get(key)!;\n\n return Object.assign(expr, {\n direction: this.#orderBy(expr.direction),\n ...this.#resolveSortOptions(options),\n });\n }\n\n // Initial state\n return this.#createDefaultExpression(key);\n }\n\n public reset(key?: Keys<T>) {\n key ? this.state.delete(key) : this.state.clear();\n }\n\n get #rowReorder() {\n // @ts-expect-error - protected member access\n return this.host.stateController.rowReorder as\n | { hasManualOrder: boolean; clearManualOrder(announce?: boolean): void }\n | undefined;\n }\n\n protected _sort(expressions: SortExpression<T> | SortExpression<T>[]) {\n const exprs = asArray(expressions);\n // Applying a sort is mutually exclusive with a manual row order (F5):\n // a real sort (any non-`none` direction) clears it, with an announcement.\n const reorder = this.#rowReorder;\n if (reorder?.hasManualOrder && exprs.some((expr) => expr.direction !== 'none')) {\n reorder.clearManualOrder(true);\n }\n\n for (const expr of exprs) {\n this.#setExpression(expr);\n }\n\n this.host.requestUpdate(PIPELINE);\n }\n\n public sort(expressions: SortExpression<T> | SortExpression<T>[]) {\n this._sort(\n asArray(expressions).map((expr) =>\n Object.assign(this.state.get(expr.key) ?? this.#createDefaultExpression(expr.key), expr)\n )\n );\n }\n\n public hostConnected() {}\n}\n"]}
1
+ {"version":3,"file":"sort.js","sourceRoot":"","sources":["../../src/controllers/sort.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReactiveController } from 'lit';\nimport { PIPELINE } from '../internal/constants.js';\nimport { awaitChildUpdates, type KeyedFlipEntry, playKeyedFlip } from '../internal/flip.js';\nimport type {\n ColumnConfiguration,\n ColumnSortConfiguration,\n GridHost,\n Keys,\n} from '../internal/types.js';\nimport { asArray } from '../internal/utils.js';\nimport type { SortExpression, SortingDirection, SortState } from '../operations/sort/types.js';\n\nexport class SortController<T extends object> implements ReactiveController {\n constructor(protected host: GridHost<T>) {\n this.host.addController(this);\n }\n\n public state: SortState<T> = new Map();\n\n get #isMultipleSort() {\n return this.host.sortConfiguration.multiple;\n }\n\n get #isTriStateSort() {\n return this.host.sortConfiguration.triState;\n }\n\n #resolveSortOptions(options?: boolean | ColumnSortConfiguration<T>) {\n const expr: Pick<SortExpression<T>, 'caseSensitive' | 'comparer'> = {\n caseSensitive: false,\n comparer: undefined,\n };\n\n if (!options || typeof options === 'boolean') {\n return expr as Partial<SortExpression<T>>;\n }\n\n return Object.assign(expr, {\n caseSensitive: options.caseSensitive,\n comparer: options.comparer,\n }) as Partial<SortExpression<T>>;\n }\n\n #createDefaultExpression(key: Keys<T>) {\n const options = this.host.getColumn(key)?.sort;\n\n return {\n key,\n direction: 'ascending',\n ...this.#resolveSortOptions(options),\n } as SortExpression<T>;\n }\n\n #orderBy(dir?: SortingDirection): SortingDirection {\n return this.#isTriStateSort\n ? dir === 'ascending'\n ? 'descending'\n : dir === 'descending'\n ? 'none'\n : 'ascending'\n : dir === 'ascending'\n ? 'descending'\n : 'ascending';\n }\n\n #emitSortingEvent(detail: SortExpression<T>) {\n return this.host.emitEvent('sorting', { detail, cancelable: true });\n }\n\n #emitSortedEvent(detail: SortExpression<T>) {\n return this.host.emitEvent('sorted', { detail });\n }\n\n #setExpression(expression: SortExpression<T>) {\n expression.direction === 'none'\n ? this.reset(expression.key)\n : this.state.set(expression.key, { ...expression });\n }\n\n public async sortFromHeaderClick(column: ColumnConfiguration<T>, additive = false) {\n const expression = this.prepareExpression(column);\n\n if (!this.#emitSortingEvent(expression)) {\n return;\n }\n\n // A plain click sorts by this column alone, clearing any other sorted\n // columns. Only a Ctrl/Cmd+click while multi-sort is enabled keeps the\n // existing sort keys and appends this column as an additional, lower-\n // priority sort. Without this gate every plain click would accumulate a\n // key, so a second column added behind a unique primary column would not\n // change the visible order at all.\n if (!this.#isMultipleSort || !additive) {\n this.reset();\n }\n\n // Capture visible-row rects keyed by data identity BEFORE the pipeline\n // runs. After the new render the virtualizer will have repositioned\n // rows; we use those captured rects as the \"First\" of a FLIP and\n // animate each row from its old viewport position back to identity.\n const beforeRects = this.#captureRowRects();\n\n this._sort(expression);\n\n await this.host.updateComplete;\n // Wait for body row updates so the new data is committed to each row\n // element before measuring the \"Last\" rect — otherwise the captured-\n // before and measured-after rects match and the animation no-ops.\n await awaitChildUpdates(this.host.rows);\n this.#playRowFlip(beforeRects);\n this.#announce(expression, column);\n this.#emitSortedEvent(expression);\n }\n\n #announce(expression: SortExpression<T>, column: ColumnConfiguration<T>) {\n const label = column.headerText ?? String(column.key);\n const message =\n expression.direction === 'none'\n ? this.host.localize('announce.sortCleared', { label })\n : this.host.localize(\n expression.direction === 'ascending'\n ? 'announce.sortedAscending'\n : 'announce.sortedDescending',\n { label }\n );\n this.host.announce(message);\n }\n\n #captureRowRects(): KeyedFlipEntry<T>[] {\n const entries: KeyedFlipEntry<T>[] = [];\n for (const row of this.host.rows) {\n const el = row as unknown as HTMLElement;\n entries.push({ key: row.data, rect: el.getBoundingClientRect() });\n }\n return entries;\n }\n\n #playRowFlip(before: ReadonlyArray<KeyedFlipEntry<T>>) {\n // After sort, the same data may be rendered by a different `<apex-grid-row>`\n // DOM element (virtualizer recycles rows). Resolve by data identity.\n const rows = this.host.rows;\n const byData = new Map<T, HTMLElement>();\n for (const row of rows) {\n byData.set(row.data, row as unknown as HTMLElement);\n }\n playKeyedFlip(before, (data) => byData.get(data) ?? null, 'y');\n }\n\n public prepareExpression({ key, sort: options }: ColumnConfiguration<T>): SortExpression<T> {\n if (this.state.has(key)) {\n const expr = this.state.get(key)!;\n\n return Object.assign(expr, {\n direction: this.#orderBy(expr.direction),\n ...this.#resolveSortOptions(options),\n });\n }\n\n // Initial state\n return this.#createDefaultExpression(key);\n }\n\n public reset(key?: Keys<T>) {\n key ? this.state.delete(key) : this.state.clear();\n }\n\n get #rowReorder() {\n // @ts-expect-error - protected member access\n return this.host.stateController.rowReorder as\n | { hasManualOrder: boolean; clearManualOrder(announce?: boolean): void }\n | undefined;\n }\n\n protected _sort(expressions: SortExpression<T> | SortExpression<T>[]) {\n const exprs = asArray(expressions);\n // Applying a sort is mutually exclusive with a manual row order (F5):\n // a real sort (any non-`none` direction) clears it, with an announcement.\n const reorder = this.#rowReorder;\n if (reorder?.hasManualOrder && exprs.some((expr) => expr.direction !== 'none')) {\n reorder.clearManualOrder(true);\n }\n\n for (const expr of exprs) {\n this.#setExpression(expr);\n }\n\n this.host.requestUpdate(PIPELINE);\n }\n\n public sort(expressions: SortExpression<T> | SortExpression<T>[]) {\n this._sort(\n asArray(expressions).map((expr) =>\n Object.assign(this.state.get(expr.key) ?? this.#createDefaultExpression(expr.key), expr)\n )\n );\n }\n\n public hostConnected() {}\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { ReactiveController } from 'lit';
2
2
  import type { GridLocaleKey, LocaleParams } from '../i18n/index.js';
3
- import { type CellDecoration, type CellDecoratorContext, type CellInteraction, type GridFeatureModule, type PresentedRow, type RowPresenterContext } from '../internal/feature-module.js';
3
+ import { type CellDecoration, type CellDecoratorContext, type CellInteraction, type GridFeatureModule, type PresentedRow, type RowAria, type RowPresenterContext } from '../internal/feature-module.js';
4
4
  import type { ActiveNode, GridHost } from '../internal/types.js';
5
5
  import { EditingController } from './editing.js';
6
6
  import { ExpansionController } from './expansion.js';
@@ -61,8 +61,8 @@ export declare class StateController<T extends object> implements ReactiveContro
61
61
  set active(node: ActiveNode<T>);
62
62
  get headerRow(): import("../components/header-row.js").default<T>;
63
63
  get scrollContainer(): import("../components/virtualizer.js").default;
64
- get paginator(): import("../components/paginator.js").default<T>;
65
- get toolbar(): import("../components/toolbar.js").default<T>;
64
+ get paginator(): import("../index.js").ApexGridPaginator<T>;
65
+ get toolbar(): import("../index.js").ApexGridToolbar<T>;
66
66
  /**
67
67
  * Cumulative pin offsets (in px) keyed by column key. Populated by the
68
68
  * {@link GridDOMController} after each layout.
@@ -88,6 +88,12 @@ export declare class StateController<T extends object> implements ReactiveContro
88
88
  * the first non-null result, or `null` when no module owns the row.
89
89
  */
90
90
  presentRow(row: T, ctx: RowPresenterContext<T>): PresentedRow | null;
91
+ /**
92
+ * Asks feature modules implementing {@link RowAriaProvider} for ARIA
93
+ * tree/expansion semantics on a normal (cell-rendered) row — e.g. pivoting's
94
+ * expandable parent rows. Returns the first non-null result, or `null`.
95
+ */
96
+ describeRow(row: T, ctx: RowPresenterContext<T>): RowAria | null;
91
97
  get decorationVersion(): number;
92
98
  /**
93
99
  * Signals that {@link CellDecorator} output may have changed. Bumps the
@@ -1,5 +1,5 @@
1
1
  import { createContext } from '@lit/context';
2
- import { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from '../internal/feature-module.js';
2
+ import { isCellDecorator, isCellInteractionHandler, isColumnMenuProvider, isRowAriaProvider, isRowPresenter, isRowTransformer, isSerializableModule, } from '../internal/feature-module.js';
3
3
  import { EditingController } from './editing.js';
4
4
  import { ExpansionController } from './expansion.js';
5
5
  import { FilterController } from './filter.js';
@@ -102,6 +102,16 @@ export class StateController {
102
102
  }
103
103
  return null;
104
104
  }
105
+ describeRow(row, ctx) {
106
+ for (const controller of this.modules.values()) {
107
+ if (isRowAriaProvider(controller)) {
108
+ const aria = controller.describeRow(row, ctx);
109
+ if (aria)
110
+ return aria;
111
+ }
112
+ }
113
+ return null;
114
+ }
105
115
  #decorationVersion;
106
116
  get decorationVersion() {
107
117
  return this.#decorationVersion;
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/controllers/state.ts"],"names":[],"mappings":"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","sourcesContent":["import { createContext } from '@lit/context';\nimport type { ReactiveController } from 'lit';\nimport type { GridLocaleKey, LocaleParams } from '../i18n/index.js';\nimport {\n type CellDecoration,\n type CellDecoratorContext,\n type CellInteraction,\n type GridFeatureModule,\n isCellDecorator,\n isCellInteractionHandler,\n isColumnMenuProvider,\n isRowPresenter,\n isRowTransformer,\n isSerializableModule,\n type PresentedRow,\n type RowPresenterContext,\n} from '../internal/feature-module.js';\nimport type { ActiveNode, GridHost } from '../internal/types.js';\nimport { EditingController } from './editing.js';\nimport { ExpansionController } from './expansion.js';\nimport { FilterController } from './filter.js';\nimport { HistoryController } from './history.js';\nimport { NavigationController } from './navigation.js';\nimport { PaginationController } from './pagination.js';\nimport { ReorderController } from './reorder.js';\nimport { ResizeController } from './resize.js';\nimport { RowPinController } from './row-pin.js';\nimport { RowReorderController } from './row-reorder.js';\nimport { SelectionController } from './selection.js';\nimport { SortController } from './sort.js';\nimport { TreeController } from './tree.js';\n\nexport class StateController<T extends object> implements ReactiveController {\n public sorting!: SortController<T>;\n public filtering!: FilterController<T>;\n public navigation!: NavigationController<T>;\n public resizing!: ResizeController<T>;\n public pagination!: PaginationController<T>;\n public reordering!: ReorderController<T>;\n public editing!: EditingController<T>;\n public history!: HistoryController<T>;\n public selection!: SelectionController<T>;\n public expansion!: ExpansionController<T>;\n public tree!: TreeController<T>;\n public rowPin!: RowPinController<T>;\n public rowReorder!: RowReorderController<T>;\n\n /**\n * Optional feature controllers contributed by {@link GridFeatureModule}s,\n * keyed by module id. Empty for the community `<apex-grid>` element; populated\n * by derived grids (e.g. `@apexcharts/grid-enterprise`) that pass modules to\n * the constructor.\n */\n public readonly modules = new Map<string, ReactiveController>();\n\n /**\n * Current message in the grid's polite live region. Bound by the host's\n * `renderLiveRegion()` template; mutated through {@link setAnnouncement}\n * so screen readers re-announce on every change.\n */\n public announcement = '';\n #announceToken = 0;\n\n /**\n * Updates the polite live region's text. Repeats are forced to fire by\n * appending a zero-width space — screen readers ignore unchanged content,\n * so two identical sort announcements wouldn't otherwise be read aloud.\n */\n public setAnnouncement(message: string): void {\n if (!message) {\n this.announcement = '';\n this.host.requestUpdate();\n return;\n }\n this.#announceToken = (this.#announceToken + 1) % 2;\n this.announcement = this.#announceToken ? message : `${message} `;\n this.host.requestUpdate();\n }\n\n /**\n * Resolves a built-in locale key to its display string, honoring the host\n * grid's {@link ApexGrid.localeText} overrides. Thin proxy to\n * {@link ApexGrid.localize} so components can localize via `this.state`.\n */\n public localize(key: GridLocaleKey, params?: LocaleParams, fallback?: string): string {\n return this.host.localize(key, params, fallback);\n }\n\n public get active() {\n return this.navigation.active;\n }\n\n public set active(node: ActiveNode<T>) {\n this.navigation.active = node;\n }\n\n public get headerRow() {\n // @ts-expect-error - Protected member access\n return this.host.headerRow;\n }\n\n public get scrollContainer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n public get paginator() {\n // @ts-expect-error - Protected member access\n return this.host.paginator;\n }\n\n public get toolbar() {\n // @ts-expect-error - Protected member access\n return this.host.toolbar;\n }\n\n /**\n * Cumulative pin offsets (in px) keyed by column key. Populated by the\n * {@link GridDOMController} after each layout.\n */\n public get pinOffsets(): Map<unknown, number> {\n // @ts-expect-error - Protected member access\n const dom = this.host.DOM as { pinOffsets?: Map<unknown, number> } | undefined;\n return dom?.pinOffsets ?? new Map();\n }\n\n constructor(\n public host: GridHost<T>,\n private extraModules: ReadonlyArray<GridFeatureModule<T>> = []\n ) {\n this.host.addController(this);\n this.init();\n }\n\n protected init() {\n this.sorting = new SortController(this.host);\n this.filtering = new FilterController(this.host);\n this.navigation = new NavigationController(this.host);\n this.resizing = new ResizeController(this.host);\n this.pagination = new PaginationController(this.host);\n this.reordering = new ReorderController(this.host);\n this.history = new HistoryController(this.host);\n this.editing = new EditingController(this.host, this.history);\n this.selection = new SelectionController(this.host);\n this.expansion = new ExpansionController(this.host);\n this.tree = new TreeController(this.host);\n this.rowPin = new RowPinController(this.host);\n this.rowReorder = new RowReorderController(this.host);\n\n for (const module of this.extraModules) {\n if (this.modules.has(module.id)) continue;\n this.modules.set(module.id, module.create(this.host, this));\n }\n }\n\n /**\n * Look up a feature controller contributed by a {@link GridFeatureModule},\n * by its module id. Returns `undefined` when no such module is registered.\n */\n public module<C extends ReactiveController>(id: string): C | undefined {\n return this.modules.get(id) as C | undefined;\n }\n\n /**\n * Runs the post-pipeline row transforms contributed by feature modules\n * implementing {@link RowTransformer}, in registration order. Returns the\n * input unchanged when no such module is registered — the community grid path\n * is a no-op pass-through.\n */\n public applyModuleTransforms(rows: T[]): T[] {\n let result = rows;\n for (const controller of this.modules.values()) {\n if (isRowTransformer<T>(controller)) {\n result = controller.processRows(result);\n }\n }\n return result;\n }\n\n /**\n * Asks feature modules implementing {@link RowPresenter} whether they render\n * the given row as full-width custom content (e.g. a group header). Returns\n * the first non-null result, or `null` when no module owns the row.\n */\n public presentRow(row: T, ctx: RowPresenterContext<T>): PresentedRow | null {\n for (const controller of this.modules.values()) {\n if (isRowPresenter<T>(controller)) {\n const presented = controller.presentRow(row, ctx);\n if (presented) return presented;\n }\n }\n return null;\n }\n\n /**\n * Monotonic token bumped by {@link bumpDecoration} whenever module-driven cell\n * decoration changes. Forwarded down to each cell as a reactive property so a\n * decoration-only change (e.g. dragging a selection range) re-renders cells\n * without re-running the data pipeline. Always `0` for the community grid.\n */\n #decorationVersion = 0;\n\n public get decorationVersion(): number {\n return this.#decorationVersion;\n }\n\n /**\n * Signals that {@link CellDecorator} output may have changed. Bumps the\n * {@link decorationVersion} and requests a host update so cells re-run their\n * decoration. Called by feature modules after mutating decoration state.\n */\n public bumpDecoration(): void {\n this.#decorationVersion += 1;\n this.host.requestUpdate();\n }\n\n /**\n * Whether any feature module implementing {@link ColumnMenuProvider} offers a\n * column header menu. The header uses this to show its kebab button even on\n * columns that are neither sortable nor resizable, so a module (the enterprise\n * context menu) can surface pin / hide / group / chart actions. Always `false`\n * for the community grid (no modules).\n */\n public get hasColumnMenu(): boolean {\n for (const controller of this.modules.values()) {\n if (isColumnMenuProvider(controller) && controller.providesColumnMenu()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Collects per-cell decoration contributed by feature modules implementing\n * {@link CellDecorator}, merging their attribute maps (later modules win on a\n * key clash). Returns `null` when no module decorates the cell — the community\n * grid path, where each cell applies nothing.\n */\n public decorateCell(ctx: CellDecoratorContext<T>): CellDecoration | null {\n let attributes: Record<string, string | null | undefined> | null = null;\n for (const controller of this.modules.values()) {\n if (isCellDecorator<T>(controller)) {\n const decoration = controller.decorateCell(ctx);\n if (decoration) {\n attributes ??= {};\n Object.assign(attributes, decoration.attributes);\n }\n }\n }\n return attributes ? { attributes } : null;\n }\n\n /**\n * Forwards a body-cell pointer interaction to every feature module that\n * implements {@link CellInteractionHandler}. No-op for the community grid\n * (no modules); the grid only calls this when modules are registered.\n */\n public handleCellInteraction(interaction: CellInteraction<T>): void {\n for (const controller of this.modules.values()) {\n if (isCellInteractionHandler<T>(controller)) {\n controller.handleCellInteraction(interaction);\n }\n }\n }\n\n /**\n * Collects per-module snapshot state from feature controllers implementing\n * {@link SerializableModule}, keyed by module id. Returns an empty object for\n * the community grid (no modules). Used by `ApexGrid.getState`.\n */\n public serializeModuleState(): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller)) {\n out[id] = controller.serializeState();\n }\n }\n return out;\n }\n\n /**\n * Dispatches previously-serialized state back to the matching feature modules\n * (by id) that implement {@link SerializableModule}. Missing ids and unknown\n * modules are ignored. Used by `ApexGrid.setState`.\n */\n public restoreModuleState(data: Record<string, unknown> | undefined): void {\n if (!data) return;\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller) && Object.hasOwn(data, id)) {\n controller.restoreState(data[id]);\n }\n }\n }\n\n public hostConnected() {}\n\n public hostUpdate(): void {\n this.headerRow?.requestUpdate();\n this.scrollContainer?.requestUpdate();\n this.paginator?.requestUpdate();\n this.toolbar?.requestUpdate();\n }\n}\n\nexport const gridStateContext = createContext<StateController<any>>('gridStateController');\n"]}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/controllers/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,OAAO,EAKL,eAAe,EACf,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,GAIrB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,OAAO,eAAe;IA6B1B,cAAc,CAAK;IAOZ,eAAe,CAAC,OAAe;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,cAAc,GAAG,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACpD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC;QAClE,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IAOM,QAAQ,CAAC,GAAkB,EAAE,MAAqB,EAAE,QAAiB;QAC1E,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;IAChC,CAAC;IAED,IAAW,MAAM,CAAC,IAAmB;QACnC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC;IAChC,CAAC;IAED,IAAW,SAAS;QAElB,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;IAC7B,CAAC;IAED,IAAW,eAAe;QAExB,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;IACnC,CAAC;IAED,IAAW,SAAS;QAElB,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;IAC7B,CAAC;IAED,IAAW,OAAO;QAEhB,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC3B,CAAC;IAMD,IAAW,UAAU;QAEnB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAwD,CAAC;QAC/E,OAAO,GAAG,EAAE,UAAU,IAAI,IAAI,GAAG,EAAE,CAAC;IACtC,CAAC;IAED,YACS,IAAiB,EAChB,eAAoD,EAAE;QADvD,SAAI,GAAJ,IAAI,CAAa;QAChB,iBAAY,GAAZ,YAAY,CAA0C;QA3EhD,YAAO,GAAG,IAAI,GAAG,EAA8B,CAAC;QAOzD,iBAAY,GAAG,EAAE,CAAC;QACzB,mBAAc,GAAG,CAAC,CAAC;QA0JnB,uBAAkB,GAAG,CAAC,CAAC;QArFrB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAES,IAAI;QACZ,IAAI,CAAC,OAAO,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,UAAU,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,UAAU,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC,SAAS,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEtD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAAE,SAAS;YAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAMM,MAAM,CAA+B,EAAU;QACpD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAkB,CAAC;IAC/C,CAAC;IAQM,qBAAqB,CAAC,IAAS;QACpC,IAAI,MAAM,GAAG,IAAI,CAAC;QAClB,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,IAAI,gBAAgB,CAAI,UAAU,CAAC,EAAE,CAAC;gBACpC,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAOM,UAAU,CAAC,GAAM,EAAE,GAA2B;QACnD,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,IAAI,cAAc,CAAI,UAAU,CAAC,EAAE,CAAC;gBAClC,MAAM,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAClD,IAAI,SAAS;oBAAE,OAAO,SAAS,CAAC;YAClC,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAOM,WAAW,CAAC,GAAM,EAAE,GAA2B;QACpD,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,IAAI,iBAAiB,CAAI,UAAU,CAAC,EAAE,CAAC;gBACrC,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC9C,IAAI,IAAI;oBAAE,OAAO,IAAI,CAAC;YACxB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAQD,kBAAkB,CAAK;IAEvB,IAAW,iBAAiB;QAC1B,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAOM,cAAc;QACnB,IAAI,CAAC,kBAAkB,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;IAC5B,CAAC;IASD,IAAW,aAAa;QACtB,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,IAAI,oBAAoB,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,kBAAkB,EAAE,EAAE,CAAC;gBACxE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAQM,YAAY,CAAC,GAA4B;QAC9C,IAAI,UAAU,GAAqD,IAAI,CAAC;QACxE,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,IAAI,eAAe,CAAI,UAAU,CAAC,EAAE,CAAC;gBACnC,MAAM,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;gBAChD,IAAI,UAAU,EAAE,CAAC;oBACf,UAAU,KAAK,EAAE,CAAC;oBAClB,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IAOM,qBAAqB,CAAC,WAA+B;QAC1D,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC/C,IAAI,wBAAwB,CAAI,UAAU,CAAC,EAAE,CAAC;gBAC5C,UAAU,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAOM,oBAAoB;QACzB,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC5C,IAAI,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;gBACrC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,cAAc,EAAE,CAAC;YACxC,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAOM,kBAAkB,CAAC,IAAyC;QACjE,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,KAAK,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC5C,IAAI,oBAAoB,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;gBAChE,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;IACH,CAAC;IAEM,aAAa,KAAI,CAAC;IAElB,UAAU;QACf,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,CAAC;QAChC,IAAI,CAAC,eAAe,EAAE,aAAa,EAAE,CAAC;QACtC,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,CAAC;QAChC,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,CAAC;IAChC,CAAC;CACF;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAuB,qBAAqB,CAAC,CAAC","sourcesContent":["import { createContext } from '@lit/context';\nimport type { ReactiveController } from 'lit';\nimport type { GridLocaleKey, LocaleParams } from '../i18n/index.js';\nimport {\n type CellDecoration,\n type CellDecoratorContext,\n type CellInteraction,\n type GridFeatureModule,\n isCellDecorator,\n isCellInteractionHandler,\n isColumnMenuProvider,\n isRowAriaProvider,\n isRowPresenter,\n isRowTransformer,\n isSerializableModule,\n type PresentedRow,\n type RowAria,\n type RowPresenterContext,\n} from '../internal/feature-module.js';\nimport type { ActiveNode, GridHost } from '../internal/types.js';\nimport { EditingController } from './editing.js';\nimport { ExpansionController } from './expansion.js';\nimport { FilterController } from './filter.js';\nimport { HistoryController } from './history.js';\nimport { NavigationController } from './navigation.js';\nimport { PaginationController } from './pagination.js';\nimport { ReorderController } from './reorder.js';\nimport { ResizeController } from './resize.js';\nimport { RowPinController } from './row-pin.js';\nimport { RowReorderController } from './row-reorder.js';\nimport { SelectionController } from './selection.js';\nimport { SortController } from './sort.js';\nimport { TreeController } from './tree.js';\n\nexport class StateController<T extends object> implements ReactiveController {\n public sorting!: SortController<T>;\n public filtering!: FilterController<T>;\n public navigation!: NavigationController<T>;\n public resizing!: ResizeController<T>;\n public pagination!: PaginationController<T>;\n public reordering!: ReorderController<T>;\n public editing!: EditingController<T>;\n public history!: HistoryController<T>;\n public selection!: SelectionController<T>;\n public expansion!: ExpansionController<T>;\n public tree!: TreeController<T>;\n public rowPin!: RowPinController<T>;\n public rowReorder!: RowReorderController<T>;\n\n /**\n * Optional feature controllers contributed by {@link GridFeatureModule}s,\n * keyed by module id. Empty for the community `<apex-grid>` element; populated\n * by derived grids (e.g. `@apexcharts/grid-enterprise`) that pass modules to\n * the constructor.\n */\n public readonly modules = new Map<string, ReactiveController>();\n\n /**\n * Current message in the grid's polite live region. Bound by the host's\n * `renderLiveRegion()` template; mutated through {@link setAnnouncement}\n * so screen readers re-announce on every change.\n */\n public announcement = '';\n #announceToken = 0;\n\n /**\n * Updates the polite live region's text. Repeats are forced to fire by\n * appending a zero-width space — screen readers ignore unchanged content,\n * so two identical sort announcements wouldn't otherwise be read aloud.\n */\n public setAnnouncement(message: string): void {\n if (!message) {\n this.announcement = '';\n this.host.requestUpdate();\n return;\n }\n this.#announceToken = (this.#announceToken + 1) % 2;\n this.announcement = this.#announceToken ? message : `${message} `;\n this.host.requestUpdate();\n }\n\n /**\n * Resolves a built-in locale key to its display string, honoring the host\n * grid's {@link ApexGrid.localeText} overrides. Thin proxy to\n * {@link ApexGrid.localize} so components can localize via `this.state`.\n */\n public localize(key: GridLocaleKey, params?: LocaleParams, fallback?: string): string {\n return this.host.localize(key, params, fallback);\n }\n\n public get active() {\n return this.navigation.active;\n }\n\n public set active(node: ActiveNode<T>) {\n this.navigation.active = node;\n }\n\n public get headerRow() {\n // @ts-expect-error - Protected member access\n return this.host.headerRow;\n }\n\n public get scrollContainer() {\n // @ts-expect-error - Protected member access\n return this.host.scrollContainer;\n }\n\n public get paginator() {\n // @ts-expect-error - Protected member access\n return this.host.paginator;\n }\n\n public get toolbar() {\n // @ts-expect-error - Protected member access\n return this.host.toolbar;\n }\n\n /**\n * Cumulative pin offsets (in px) keyed by column key. Populated by the\n * {@link GridDOMController} after each layout.\n */\n public get pinOffsets(): Map<unknown, number> {\n // @ts-expect-error - Protected member access\n const dom = this.host.DOM as { pinOffsets?: Map<unknown, number> } | undefined;\n return dom?.pinOffsets ?? new Map();\n }\n\n constructor(\n public host: GridHost<T>,\n private extraModules: ReadonlyArray<GridFeatureModule<T>> = []\n ) {\n this.host.addController(this);\n this.init();\n }\n\n protected init() {\n this.sorting = new SortController(this.host);\n this.filtering = new FilterController(this.host);\n this.navigation = new NavigationController(this.host);\n this.resizing = new ResizeController(this.host);\n this.pagination = new PaginationController(this.host);\n this.reordering = new ReorderController(this.host);\n this.history = new HistoryController(this.host);\n this.editing = new EditingController(this.host, this.history);\n this.selection = new SelectionController(this.host);\n this.expansion = new ExpansionController(this.host);\n this.tree = new TreeController(this.host);\n this.rowPin = new RowPinController(this.host);\n this.rowReorder = new RowReorderController(this.host);\n\n for (const module of this.extraModules) {\n if (this.modules.has(module.id)) continue;\n this.modules.set(module.id, module.create(this.host, this));\n }\n }\n\n /**\n * Look up a feature controller contributed by a {@link GridFeatureModule},\n * by its module id. Returns `undefined` when no such module is registered.\n */\n public module<C extends ReactiveController>(id: string): C | undefined {\n return this.modules.get(id) as C | undefined;\n }\n\n /**\n * Runs the post-pipeline row transforms contributed by feature modules\n * implementing {@link RowTransformer}, in registration order. Returns the\n * input unchanged when no such module is registered — the community grid path\n * is a no-op pass-through.\n */\n public applyModuleTransforms(rows: T[]): T[] {\n let result = rows;\n for (const controller of this.modules.values()) {\n if (isRowTransformer<T>(controller)) {\n result = controller.processRows(result);\n }\n }\n return result;\n }\n\n /**\n * Asks feature modules implementing {@link RowPresenter} whether they render\n * the given row as full-width custom content (e.g. a group header). Returns\n * the first non-null result, or `null` when no module owns the row.\n */\n public presentRow(row: T, ctx: RowPresenterContext<T>): PresentedRow | null {\n for (const controller of this.modules.values()) {\n if (isRowPresenter<T>(controller)) {\n const presented = controller.presentRow(row, ctx);\n if (presented) return presented;\n }\n }\n return null;\n }\n\n /**\n * Asks feature modules implementing {@link RowAriaProvider} for ARIA\n * tree/expansion semantics on a normal (cell-rendered) row — e.g. pivoting's\n * expandable parent rows. Returns the first non-null result, or `null`.\n */\n public describeRow(row: T, ctx: RowPresenterContext<T>): RowAria | null {\n for (const controller of this.modules.values()) {\n if (isRowAriaProvider<T>(controller)) {\n const aria = controller.describeRow(row, ctx);\n if (aria) return aria;\n }\n }\n return null;\n }\n\n /**\n * Monotonic token bumped by {@link bumpDecoration} whenever module-driven cell\n * decoration changes. Forwarded down to each cell as a reactive property so a\n * decoration-only change (e.g. dragging a selection range) re-renders cells\n * without re-running the data pipeline. Always `0` for the community grid.\n */\n #decorationVersion = 0;\n\n public get decorationVersion(): number {\n return this.#decorationVersion;\n }\n\n /**\n * Signals that {@link CellDecorator} output may have changed. Bumps the\n * {@link decorationVersion} and requests a host update so cells re-run their\n * decoration. Called by feature modules after mutating decoration state.\n */\n public bumpDecoration(): void {\n this.#decorationVersion += 1;\n this.host.requestUpdate();\n }\n\n /**\n * Whether any feature module implementing {@link ColumnMenuProvider} offers a\n * column header menu. The header uses this to show its kebab button even on\n * columns that are neither sortable nor resizable, so a module (the enterprise\n * context menu) can surface pin / hide / group / chart actions. Always `false`\n * for the community grid (no modules).\n */\n public get hasColumnMenu(): boolean {\n for (const controller of this.modules.values()) {\n if (isColumnMenuProvider(controller) && controller.providesColumnMenu()) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Collects per-cell decoration contributed by feature modules implementing\n * {@link CellDecorator}, merging their attribute maps (later modules win on a\n * key clash). Returns `null` when no module decorates the cell — the community\n * grid path, where each cell applies nothing.\n */\n public decorateCell(ctx: CellDecoratorContext<T>): CellDecoration | null {\n let attributes: Record<string, string | null | undefined> | null = null;\n for (const controller of this.modules.values()) {\n if (isCellDecorator<T>(controller)) {\n const decoration = controller.decorateCell(ctx);\n if (decoration) {\n attributes ??= {};\n Object.assign(attributes, decoration.attributes);\n }\n }\n }\n return attributes ? { attributes } : null;\n }\n\n /**\n * Forwards a body-cell pointer interaction to every feature module that\n * implements {@link CellInteractionHandler}. No-op for the community grid\n * (no modules); the grid only calls this when modules are registered.\n */\n public handleCellInteraction(interaction: CellInteraction<T>): void {\n for (const controller of this.modules.values()) {\n if (isCellInteractionHandler<T>(controller)) {\n controller.handleCellInteraction(interaction);\n }\n }\n }\n\n /**\n * Collects per-module snapshot state from feature controllers implementing\n * {@link SerializableModule}, keyed by module id. Returns an empty object for\n * the community grid (no modules). Used by `ApexGrid.getState`.\n */\n public serializeModuleState(): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller)) {\n out[id] = controller.serializeState();\n }\n }\n return out;\n }\n\n /**\n * Dispatches previously-serialized state back to the matching feature modules\n * (by id) that implement {@link SerializableModule}. Missing ids and unknown\n * modules are ignored. Used by `ApexGrid.setState`.\n */\n public restoreModuleState(data: Record<string, unknown> | undefined): void {\n if (!data) return;\n for (const [id, controller] of this.modules) {\n if (isSerializableModule(controller) && Object.hasOwn(data, id)) {\n controller.restoreState(data[id]);\n }\n }\n }\n\n public hostConnected() {}\n\n public hostUpdate(): void {\n this.headerRow?.requestUpdate();\n this.scrollContainer?.requestUpdate();\n this.paginator?.requestUpdate();\n this.toolbar?.requestUpdate();\n }\n}\n\nexport const gridStateContext = createContext<StateController<any>>('gridStateController');\n"]}