@aquera/nile-elements 1.5.4 → 1.5.6

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 (297) hide show
  1. package/README.md +10 -0
  2. package/demo/index.css +9 -0
  3. package/dist/index.cjs.js +1 -1
  4. package/dist/index.esm.js +1 -1
  5. package/dist/index.js +871 -255
  6. package/dist/nile-auto-complete/nile-auto-complete.css.cjs.js +1 -1
  7. package/dist/nile-auto-complete/nile-auto-complete.css.cjs.js.map +1 -1
  8. package/dist/nile-auto-complete/nile-auto-complete.css.esm.js +13 -2
  9. package/dist/nile-button/nile-button.cjs.js +1 -1
  10. package/dist/nile-button/nile-button.cjs.js.map +1 -1
  11. package/dist/nile-button/nile-button.css.cjs.js +1 -1
  12. package/dist/nile-button/nile-button.css.cjs.js.map +1 -1
  13. package/dist/nile-button/nile-button.css.esm.js +89 -33
  14. package/dist/nile-button/nile-button.esm.js +2 -2
  15. package/dist/nile-calendar/nile-calendar.cjs.js +1 -1
  16. package/dist/nile-calendar/nile-calendar.cjs.js.map +1 -1
  17. package/dist/nile-calendar/nile-calendar.css.cjs.js +1 -1
  18. package/dist/nile-calendar/nile-calendar.css.cjs.js.map +1 -1
  19. package/dist/nile-calendar/nile-calendar.css.esm.js +59 -2
  20. package/dist/nile-calendar/nile-calendar.esm.js +16 -10
  21. package/dist/nile-checkbox/nile-checkbox.css.cjs.js +1 -1
  22. package/dist/nile-checkbox/nile-checkbox.css.cjs.js.map +1 -1
  23. package/dist/nile-checkbox/nile-checkbox.css.esm.js +4 -5
  24. package/dist/nile-chip/nile-chip.css.cjs.js +1 -1
  25. package/dist/nile-chip/nile-chip.css.cjs.js.map +1 -1
  26. package/dist/nile-chip/nile-chip.css.esm.js +37 -23
  27. package/dist/nile-code-editor/nile-code-editor.cjs.js +1 -1
  28. package/dist/nile-code-editor/nile-code-editor.cjs.js.map +1 -1
  29. package/dist/nile-code-editor/nile-code-editor.css.cjs.js +1 -1
  30. package/dist/nile-code-editor/nile-code-editor.css.cjs.js.map +1 -1
  31. package/dist/nile-code-editor/nile-code-editor.css.esm.js +7 -6
  32. package/dist/nile-code-editor/nile-code-editor.esm.js +1 -1
  33. package/dist/nile-date-picker/nile-date-picker.cjs.js +1 -1
  34. package/dist/nile-date-picker/nile-date-picker.cjs.js.map +1 -1
  35. package/dist/nile-date-picker/nile-date-picker.esm.js +4 -4
  36. package/dist/nile-detail/index.cjs.js +2 -0
  37. package/dist/nile-detail/index.cjs.js.map +1 -0
  38. package/dist/nile-detail/index.esm.js +1 -0
  39. package/dist/nile-detail/nile-detail.cjs.js +2 -0
  40. package/dist/nile-detail/nile-detail.cjs.js.map +1 -0
  41. package/dist/nile-detail/nile-detail.css.cjs.js +2 -0
  42. package/dist/nile-detail/nile-detail.css.cjs.js.map +1 -0
  43. package/dist/nile-detail/nile-detail.css.esm.js +149 -0
  44. package/dist/nile-detail/nile-detail.esm.js +45 -0
  45. package/dist/nile-detail/nile-detail.utils.cjs.js +2 -0
  46. package/dist/nile-detail/nile-detail.utils.cjs.js.map +1 -0
  47. package/dist/nile-detail/nile-detail.utils.esm.js +1 -0
  48. package/dist/nile-dropdown/nile-dropdown.cjs.js +1 -1
  49. package/dist/nile-dropdown/nile-dropdown.cjs.js.map +1 -1
  50. package/dist/nile-dropdown/nile-dropdown.esm.js +1 -1
  51. package/dist/nile-file-upload/utils/file-validation.util.cjs.js +2 -2
  52. package/dist/nile-file-upload/utils/file-validation.util.cjs.js.map +1 -1
  53. package/dist/nile-file-upload/utils/file-validation.util.esm.js +1 -1
  54. package/dist/nile-filter-chip/nile-filter-chip.cjs.js +1 -1
  55. package/dist/nile-filter-chip/nile-filter-chip.cjs.js.map +1 -1
  56. package/dist/nile-filter-chip/nile-filter-chip.css.cjs.js +1 -1
  57. package/dist/nile-filter-chip/nile-filter-chip.css.cjs.js.map +1 -1
  58. package/dist/nile-filter-chip/nile-filter-chip.css.esm.js +24 -2
  59. package/dist/nile-filter-chip/nile-filter-chip.esm.js +2 -2
  60. package/dist/nile-inline-edit/nile-inline-edit.cjs.js +1 -1
  61. package/dist/nile-inline-edit/nile-inline-edit.cjs.js.map +1 -1
  62. package/dist/nile-inline-edit/nile-inline-edit.css.cjs.js +1 -1
  63. package/dist/nile-inline-edit/nile-inline-edit.css.cjs.js.map +1 -1
  64. package/dist/nile-inline-edit/nile-inline-edit.css.esm.js +15 -6
  65. package/dist/nile-inline-edit/nile-inline-edit.esm.js +2 -2
  66. package/dist/nile-inline-sidebar/nile-inline-sidebar.cjs.js +1 -1
  67. package/dist/nile-inline-sidebar/nile-inline-sidebar.cjs.js.map +1 -1
  68. package/dist/nile-inline-sidebar/nile-inline-sidebar.css.cjs.js +1 -1
  69. package/dist/nile-inline-sidebar/nile-inline-sidebar.css.cjs.js.map +1 -1
  70. package/dist/nile-inline-sidebar/nile-inline-sidebar.css.esm.js +19 -0
  71. package/dist/nile-inline-sidebar/nile-inline-sidebar.esm.js +16 -14
  72. package/dist/nile-inline-sidebar-item/nile-inline-sidebar-item.cjs.js +1 -1
  73. package/dist/nile-inline-sidebar-item/nile-inline-sidebar-item.cjs.js.map +1 -1
  74. package/dist/nile-inline-sidebar-item/nile-inline-sidebar-item.esm.js +8 -3
  75. package/dist/nile-input/nile-input.css.cjs.js +1 -1
  76. package/dist/nile-input/nile-input.css.cjs.js.map +1 -1
  77. package/dist/nile-input/nile-input.css.esm.js +4 -4
  78. package/dist/nile-link/nile-link.cjs.js +1 -1
  79. package/dist/nile-link/nile-link.cjs.js.map +1 -1
  80. package/dist/nile-link/nile-link.css.cjs.js +1 -1
  81. package/dist/nile-link/nile-link.css.cjs.js.map +1 -1
  82. package/dist/nile-link/nile-link.css.esm.js +3 -4
  83. package/dist/nile-link/nile-link.esm.js +2 -2
  84. package/dist/nile-pagination/nile-pagination.cjs.js +1 -1
  85. package/dist/nile-pagination/nile-pagination.cjs.js.map +1 -1
  86. package/dist/nile-pagination/nile-pagination.css.cjs.js +1 -1
  87. package/dist/nile-pagination/nile-pagination.css.cjs.js.map +1 -1
  88. package/dist/nile-pagination/nile-pagination.css.esm.js +109 -5
  89. package/dist/nile-pagination/nile-pagination.esm.js +70 -3
  90. package/dist/nile-qr-code/index.cjs.js +2 -0
  91. package/dist/nile-qr-code/index.cjs.js.map +1 -0
  92. package/dist/nile-qr-code/index.esm.js +1 -0
  93. package/dist/nile-qr-code/nile-qr-code-utils.cjs.js +2 -0
  94. package/dist/nile-qr-code/nile-qr-code-utils.cjs.js.map +1 -0
  95. package/dist/nile-qr-code/nile-qr-code-utils.esm.js +1 -0
  96. package/dist/nile-qr-code/nile-qr-code.cjs.js +2 -0
  97. package/dist/nile-qr-code/nile-qr-code.cjs.js.map +1 -0
  98. package/dist/nile-qr-code/nile-qr-code.css.cjs.js +2 -0
  99. package/dist/nile-qr-code/nile-qr-code.css.cjs.js.map +1 -0
  100. package/dist/nile-qr-code/nile-qr-code.css.esm.js +12 -0
  101. package/dist/nile-qr-code/nile-qr-code.esm.js +9 -0
  102. package/dist/nile-radio/nile-radio.css.cjs.js +1 -1
  103. package/dist/nile-radio/nile-radio.css.cjs.js.map +1 -1
  104. package/dist/nile-radio/nile-radio.css.esm.js +1 -1
  105. package/dist/nile-rich-text-editor/nile-rich-text-editor.cjs.js +1 -1
  106. package/dist/nile-rich-text-editor/nile-rich-text-editor.cjs.js.map +1 -1
  107. package/dist/nile-rich-text-editor/nile-rich-text-editor.css.cjs.js +1 -1
  108. package/dist/nile-rich-text-editor/nile-rich-text-editor.css.cjs.js.map +1 -1
  109. package/dist/nile-rich-text-editor/nile-rich-text-editor.css.esm.js +25 -6
  110. package/dist/nile-rich-text-editor/nile-rich-text-editor.esm.js +1 -1
  111. package/dist/nile-rich-text-editor/nile-rte-select.cjs.js +1 -1
  112. package/dist/nile-rich-text-editor/nile-rte-select.cjs.js.map +1 -1
  113. package/dist/nile-rich-text-editor/nile-rte-select.esm.js +4 -3
  114. package/dist/nile-select/nile-select.css.cjs.js +1 -1
  115. package/dist/nile-select/nile-select.css.cjs.js.map +1 -1
  116. package/dist/nile-select/nile-select.css.esm.js +7 -4
  117. package/dist/nile-slide-toggle/nile-slide-toggle.css.cjs.js +1 -1
  118. package/dist/nile-slide-toggle/nile-slide-toggle.css.cjs.js.map +1 -1
  119. package/dist/nile-slide-toggle/nile-slide-toggle.css.esm.js +5 -1
  120. package/dist/nile-textarea/nile-textarea.css.cjs.js +1 -1
  121. package/dist/nile-textarea/nile-textarea.css.cjs.js.map +1 -1
  122. package/dist/nile-textarea/nile-textarea.css.esm.js +10 -5
  123. package/dist/nile-virtual-select/nile-virtual-select.css.cjs.js +1 -1
  124. package/dist/nile-virtual-select/nile-virtual-select.css.cjs.js.map +1 -1
  125. package/dist/nile-virtual-select/nile-virtual-select.css.esm.js +5 -3
  126. package/dist/src/index.d.ts +2 -0
  127. package/dist/src/index.js +2 -0
  128. package/dist/src/index.js.map +1 -1
  129. package/dist/src/nile-auto-complete/nile-auto-complete.css.js +11 -0
  130. package/dist/src/nile-auto-complete/nile-auto-complete.css.js.map +1 -1
  131. package/dist/src/nile-button/nile-button.css.js +89 -33
  132. package/dist/src/nile-button/nile-button.css.js.map +1 -1
  133. package/dist/src/nile-button/nile-button.js +5 -5
  134. package/dist/src/nile-button/nile-button.js.map +1 -1
  135. package/dist/src/nile-calendar/nile-calendar.css.js +57 -0
  136. package/dist/src/nile-calendar/nile-calendar.css.js.map +1 -1
  137. package/dist/src/nile-calendar/nile-calendar.d.ts +1 -0
  138. package/dist/src/nile-calendar/nile-calendar.js +24 -6
  139. package/dist/src/nile-calendar/nile-calendar.js.map +1 -1
  140. package/dist/src/nile-checkbox/nile-checkbox.css.js +4 -5
  141. package/dist/src/nile-checkbox/nile-checkbox.css.js.map +1 -1
  142. package/dist/src/nile-chip/nile-chip.css.js +35 -21
  143. package/dist/src/nile-chip/nile-chip.css.js.map +1 -1
  144. package/dist/src/nile-code-editor/nile-code-editor.css.js +7 -6
  145. package/dist/src/nile-code-editor/nile-code-editor.css.js.map +1 -1
  146. package/dist/src/nile-code-editor/nile-code-editor.d.ts +1 -1
  147. package/dist/src/nile-code-editor/nile-code-editor.js +7 -1
  148. package/dist/src/nile-code-editor/nile-code-editor.js.map +1 -1
  149. package/dist/src/nile-date-picker/nile-date-picker.d.ts +3 -0
  150. package/dist/src/nile-date-picker/nile-date-picker.js +22 -2
  151. package/dist/src/nile-date-picker/nile-date-picker.js.map +1 -1
  152. package/dist/src/nile-detail/index.d.ts +1 -0
  153. package/dist/src/nile-detail/index.js +2 -0
  154. package/dist/src/nile-detail/index.js.map +1 -0
  155. package/dist/src/nile-detail/nile-detail.css.d.ts +3 -0
  156. package/dist/src/nile-detail/nile-detail.css.js +152 -0
  157. package/dist/src/nile-detail/nile-detail.css.js.map +1 -0
  158. package/dist/src/nile-detail/nile-detail.d.ts +29 -0
  159. package/dist/src/nile-detail/nile-detail.js +143 -0
  160. package/dist/src/nile-detail/nile-detail.js.map +1 -0
  161. package/dist/src/nile-detail/nile-detail.test.d.ts +1 -0
  162. package/dist/src/nile-detail/nile-detail.test.js +168 -0
  163. package/dist/src/nile-detail/nile-detail.test.js.map +1 -0
  164. package/dist/src/nile-detail/nile-detail.utils.d.ts +8 -0
  165. package/dist/src/nile-detail/nile-detail.utils.js +117 -0
  166. package/dist/src/nile-detail/nile-detail.utils.js.map +1 -0
  167. package/dist/src/nile-dropdown/nile-dropdown.d.ts +1 -0
  168. package/dist/src/nile-dropdown/nile-dropdown.js +11 -0
  169. package/dist/src/nile-dropdown/nile-dropdown.js.map +1 -1
  170. package/dist/src/nile-file-upload/utils/file-validation.util.js +11 -6
  171. package/dist/src/nile-file-upload/utils/file-validation.util.js.map +1 -1
  172. package/dist/src/nile-filter-chip/nile-filter-chip.css.js +22 -0
  173. package/dist/src/nile-filter-chip/nile-filter-chip.css.js.map +1 -1
  174. package/dist/src/nile-filter-chip/nile-filter-chip.d.ts +1 -0
  175. package/dist/src/nile-filter-chip/nile-filter-chip.js +6 -0
  176. package/dist/src/nile-filter-chip/nile-filter-chip.js.map +1 -1
  177. package/dist/src/nile-inline-edit/nile-inline-edit.css.js +15 -6
  178. package/dist/src/nile-inline-edit/nile-inline-edit.css.js.map +1 -1
  179. package/dist/src/nile-inline-edit/nile-inline-edit.d.ts +2 -0
  180. package/dist/src/nile-inline-edit/nile-inline-edit.js +7 -0
  181. package/dist/src/nile-inline-edit/nile-inline-edit.js.map +1 -1
  182. package/dist/src/nile-inline-sidebar/nile-inline-sidebar.css.js +19 -0
  183. package/dist/src/nile-inline-sidebar/nile-inline-sidebar.css.js.map +1 -1
  184. package/dist/src/nile-inline-sidebar/nile-inline-sidebar.d.ts +6 -0
  185. package/dist/src/nile-inline-sidebar/nile-inline-sidebar.js +88 -4
  186. package/dist/src/nile-inline-sidebar/nile-inline-sidebar.js.map +1 -1
  187. package/dist/src/nile-inline-sidebar/nile-inline-sidebar.test.d.ts +3 -0
  188. package/dist/src/nile-inline-sidebar/nile-inline-sidebar.test.js +110 -0
  189. package/dist/src/nile-inline-sidebar/nile-inline-sidebar.test.js.map +1 -0
  190. package/dist/src/nile-inline-sidebar-group/nile-inline-sidebar-group.test.d.ts +2 -0
  191. package/dist/src/nile-inline-sidebar-group/nile-inline-sidebar-group.test.js +109 -0
  192. package/dist/src/nile-inline-sidebar-group/nile-inline-sidebar-group.test.js.map +1 -0
  193. package/dist/src/nile-inline-sidebar-item/nile-inline-sidebar-item.d.ts +4 -0
  194. package/dist/src/nile-inline-sidebar-item/nile-inline-sidebar-item.js +30 -2
  195. package/dist/src/nile-inline-sidebar-item/nile-inline-sidebar-item.js.map +1 -1
  196. package/dist/src/nile-inline-sidebar-item/nile-inline-sidebar-item.test.d.ts +2 -0
  197. package/dist/src/nile-inline-sidebar-item/nile-inline-sidebar-item.test.js +109 -0
  198. package/dist/src/nile-inline-sidebar-item/nile-inline-sidebar-item.test.js.map +1 -0
  199. package/dist/src/nile-input/nile-input.css.js +4 -4
  200. package/dist/src/nile-input/nile-input.css.js.map +1 -1
  201. package/dist/src/nile-link/nile-link.css.js +1 -2
  202. package/dist/src/nile-link/nile-link.css.js.map +1 -1
  203. package/dist/src/nile-link/nile-link.js +1 -0
  204. package/dist/src/nile-link/nile-link.js.map +1 -1
  205. package/dist/src/nile-pagination/nile-pagination.css.js +107 -3
  206. package/dist/src/nile-pagination/nile-pagination.css.js.map +1 -1
  207. package/dist/src/nile-pagination/nile-pagination.d.ts +5 -1
  208. package/dist/src/nile-pagination/nile-pagination.js +84 -1
  209. package/dist/src/nile-pagination/nile-pagination.js.map +1 -1
  210. package/dist/src/nile-pagination/nile-pagination.test.js +1187 -103
  211. package/dist/src/nile-pagination/nile-pagination.test.js.map +1 -1
  212. package/dist/src/nile-qr-code/index.d.ts +1 -0
  213. package/dist/src/nile-qr-code/index.js +2 -0
  214. package/dist/src/nile-qr-code/index.js.map +1 -0
  215. package/dist/src/nile-qr-code/nile-qr-code-utils.d.ts +15 -0
  216. package/dist/src/nile-qr-code/nile-qr-code-utils.js +678 -0
  217. package/dist/src/nile-qr-code/nile-qr-code-utils.js.map +1 -0
  218. package/dist/src/nile-qr-code/nile-qr-code.css.d.ts +12 -0
  219. package/dist/src/nile-qr-code/nile-qr-code.css.js +24 -0
  220. package/dist/src/nile-qr-code/nile-qr-code.css.js.map +1 -0
  221. package/dist/src/nile-qr-code/nile-qr-code.d.ts +127 -0
  222. package/dist/src/nile-qr-code/nile-qr-code.js +381 -0
  223. package/dist/src/nile-qr-code/nile-qr-code.js.map +1 -0
  224. package/dist/src/nile-qr-code/nile-qr-code.test.d.ts +1 -0
  225. package/dist/src/nile-qr-code/nile-qr-code.test.js +719 -0
  226. package/dist/src/nile-qr-code/nile-qr-code.test.js.map +1 -0
  227. package/dist/src/nile-radio/nile-radio.css.js +1 -1
  228. package/dist/src/nile-radio/nile-radio.css.js.map +1 -1
  229. package/dist/src/nile-rich-text-editor/nile-rich-text-editor.css.js +25 -6
  230. package/dist/src/nile-rich-text-editor/nile-rich-text-editor.css.js.map +1 -1
  231. package/dist/src/nile-rich-text-editor/nile-rich-text-editor.d.ts +1 -0
  232. package/dist/src/nile-rich-text-editor/nile-rich-text-editor.js +17 -6
  233. package/dist/src/nile-rich-text-editor/nile-rich-text-editor.js.map +1 -1
  234. package/dist/src/nile-rich-text-editor/nile-rte-select.d.ts +1 -0
  235. package/dist/src/nile-rich-text-editor/nile-rte-select.js +7 -2
  236. package/dist/src/nile-rich-text-editor/nile-rte-select.js.map +1 -1
  237. package/dist/src/nile-select/nile-select.css.js +7 -4
  238. package/dist/src/nile-select/nile-select.css.js.map +1 -1
  239. package/dist/src/nile-slide-toggle/nile-slide-toggle.css.js +5 -1
  240. package/dist/src/nile-slide-toggle/nile-slide-toggle.css.js.map +1 -1
  241. package/dist/src/nile-textarea/nile-textarea.css.js +10 -5
  242. package/dist/src/nile-textarea/nile-textarea.css.js.map +1 -1
  243. package/dist/src/nile-virtual-select/nile-virtual-select.css.js +5 -3
  244. package/dist/src/nile-virtual-select/nile-virtual-select.css.js.map +1 -1
  245. package/dist/src/version.js +1 -1
  246. package/dist/src/version.js.map +1 -1
  247. package/dist/tsconfig.tsbuildinfo +1 -1
  248. package/package.json +3 -2
  249. package/src/index.ts +3 -2
  250. package/src/nile-auto-complete/nile-auto-complete.css.ts +11 -0
  251. package/src/nile-button/nile-button.css.ts +89 -33
  252. package/src/nile-button/nile-button.ts +6 -5
  253. package/src/nile-calendar/nile-calendar.css.ts +57 -0
  254. package/src/nile-calendar/nile-calendar.ts +17 -6
  255. package/src/nile-checkbox/nile-checkbox.css.ts +4 -5
  256. package/src/nile-chip/nile-chip.css.ts +35 -21
  257. package/src/nile-code-editor/nile-code-editor.css.ts +7 -6
  258. package/src/nile-code-editor/nile-code-editor.ts +7 -1
  259. package/src/nile-date-picker/nile-date-picker.ts +22 -2
  260. package/src/nile-detail/index.ts +1 -0
  261. package/src/nile-detail/nile-detail.css.ts +153 -0
  262. package/src/nile-detail/nile-detail.test.ts +215 -0
  263. package/src/nile-detail/nile-detail.ts +140 -0
  264. package/src/nile-detail/nile-detail.utils.ts +133 -0
  265. package/src/nile-dropdown/nile-dropdown.ts +11 -0
  266. package/src/nile-file-upload/utils/file-validation.util.ts +10 -5
  267. package/src/nile-filter-chip/nile-filter-chip.css.ts +22 -0
  268. package/src/nile-filter-chip/nile-filter-chip.ts +2 -0
  269. package/src/nile-inline-edit/nile-inline-edit.css.ts +15 -6
  270. package/src/nile-inline-edit/nile-inline-edit.ts +4 -0
  271. package/src/nile-inline-sidebar/nile-inline-sidebar.css.ts +19 -0
  272. package/src/nile-inline-sidebar/nile-inline-sidebar.test.ts +108 -0
  273. package/src/nile-inline-sidebar/nile-inline-sidebar.ts +108 -5
  274. package/src/nile-inline-sidebar-group/nile-inline-sidebar-group.test.ts +107 -0
  275. package/src/nile-inline-sidebar-item/nile-inline-sidebar-item.test.ts +107 -0
  276. package/src/nile-inline-sidebar-item/nile-inline-sidebar-item.ts +34 -3
  277. package/src/nile-input/nile-input.css.ts +4 -4
  278. package/src/nile-link/nile-link.css.ts +1 -2
  279. package/src/nile-link/nile-link.ts +1 -0
  280. package/src/nile-pagination/nile-pagination.css.ts +107 -3
  281. package/src/nile-pagination/nile-pagination.test.ts +1388 -101
  282. package/src/nile-pagination/nile-pagination.ts +87 -2
  283. package/src/nile-qr-code/index.ts +1 -0
  284. package/src/nile-qr-code/nile-qr-code-utils.ts +733 -0
  285. package/src/nile-qr-code/nile-qr-code.css.ts +26 -0
  286. package/src/nile-qr-code/nile-qr-code.test.ts +879 -0
  287. package/src/nile-qr-code/nile-qr-code.ts +431 -0
  288. package/src/nile-radio/nile-radio.css.ts +1 -1
  289. package/src/nile-rich-text-editor/nile-rich-text-editor.css.ts +25 -6
  290. package/src/nile-rich-text-editor/nile-rich-text-editor.ts +14 -6
  291. package/src/nile-rich-text-editor/nile-rte-select.ts +5 -2
  292. package/src/nile-select/nile-select.css.ts +7 -4
  293. package/src/nile-slide-toggle/nile-slide-toggle.css.ts +5 -1
  294. package/src/nile-textarea/nile-textarea.css.ts +10 -5
  295. package/src/nile-virtual-select/nile-virtual-select.css.ts +5 -3
  296. package/vscode-html-custom-data.json +163 -10
  297. package/web-test-runner.config.mjs +1 -1
@@ -0,0 +1,733 @@
1
+ /**
2
+ * Copyright Aquera Inc 2023
3
+ *
4
+ * This source code is licensed under the BSD-3-Clause license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Types
12
+ // ---------------------------------------------------------------------------
13
+
14
+ export type ErrorCorrectionLevel = 'L' | 'M' | 'Q' | 'H';
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // Constants
18
+ // ---------------------------------------------------------------------------
19
+
20
+ /** Error-correction level ordinals used as array indices. */
21
+ const EC_ORDINALS: Record<ErrorCorrectionLevel, number> = { L: 0, M: 1, Q: 2, H: 3 };
22
+
23
+ /**
24
+ * Maximum number of *data* codewords for each (version, ecl) combination.
25
+ * Index: [version-1][ecl ordinal] (versions 1–40).
26
+ * Source: ISO/IEC 18004 Table 7.
27
+ */
28
+ const DATA_CODEWORDS: number[][] = [
29
+ [19, 16, 13, 9],
30
+ [34, 28, 22, 16],
31
+ [55, 44, 34, 26],
32
+ [80, 64, 48, 36],
33
+ [108, 86, 62, 46],
34
+ [136, 108, 76, 60],
35
+ [156, 124, 88, 66],
36
+ [194, 154, 110, 86],
37
+ [232, 182, 132, 100],
38
+ [274, 216, 154, 122],
39
+ [324, 254, 180, 140],
40
+ [370, 290, 206, 158],
41
+ [428, 334, 244, 180],
42
+ [461, 365, 261, 197],
43
+ [523, 415, 295, 223],
44
+ [589, 453, 325, 253],
45
+ [647, 507, 367, 283],
46
+ [721, 563, 397, 313],
47
+ [795, 627, 445, 341],
48
+ [861, 669, 485, 385],
49
+ [932, 714, 512, 406],
50
+ [1006, 782, 568, 442],
51
+ [1094, 860, 614, 464],
52
+ [1174, 914, 664, 514],
53
+ [1276, 1000, 718, 538],
54
+ [1370, 1062, 754, 596],
55
+ [1468, 1128, 808, 628],
56
+ [1531, 1193, 871, 661],
57
+ [1631, 1267, 911, 701],
58
+ [1735, 1373, 985, 745],
59
+ [1843, 1455, 1033, 793],
60
+ [1955, 1541, 1115, 845],
61
+ [2071, 1631, 1171, 901],
62
+ [2191, 1725, 1231, 961],
63
+ [2306, 1812, 1286, 986],
64
+ [2434, 1914, 1354, 1054],
65
+ [2566, 1992, 1426, 1096],
66
+ [2702, 2102, 1502, 1142],
67
+ [2812, 2216, 1582, 1222],
68
+ [2956, 2334, 1666, 1276],
69
+ ];
70
+
71
+ /**
72
+ * Total codewords per version (data + EC).
73
+ */
74
+ const TOTAL_CODEWORDS: number[] = [
75
+ 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,
76
+ 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,
77
+ 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,
78
+ 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706,
79
+ ];
80
+
81
+ /**
82
+ * Number of EC blocks (group-1 count, group-1 data-cw, group-2 count, group-2 data-cw)
83
+ * for each (version, ecl).
84
+ * Index: [version-1][ecl ordinal] → [g1Count, g1DataCw, g2Count, g2DataCw]
85
+ */
86
+ const EC_BLOCKS: number[][][] = [
87
+ /* v1 */ [[1,19,0,0],[1,16,0,0],[1,13,0,0],[1,9,0,0]],
88
+ /* v2 */ [[1,34,0,0],[1,28,0,0],[1,22,0,0],[1,16,0,0]],
89
+ /* v3 */ [[1,55,0,0],[1,44,0,0],[2,17,0,0],[2,13,0,0]],
90
+ /* v4 */ [[1,80,0,0],[2,32,0,0],[2,24,0,0],[4,9,0,0]],
91
+ /* v5 */ [[1,108,0,0],[2,43,0,0],[2,15,2,16],[2,11,2,12]],
92
+ /* v6 */ [[2,68,0,0],[4,27,0,0],[4,19,0,0],[4,15,0,0]],
93
+ /* v7 */ [[2,78,0,0],[4,31,0,0],[2,14,4,15],[4,13,1,14]],
94
+ /* v8 */ [[2,97,0,0],[2,38,2,39],[4,18,2,19],[4,14,2,15]],
95
+ /* v9 */ [[2,116,0,0],[3,36,2,37],[4,16,4,17],[4,12,4,13]],
96
+ /* v10 */ [[2,68,2,69],[4,43,1,44],[6,19,2,20],[6,15,2,16]],
97
+ /* v11 */ [[4,81,0,0],[1,50,4,51],[4,22,4,23],[3,12,8,13]],
98
+ /* v12 */ [[2,92,2,93],[6,36,2,37],[4,20,6,21],[7,14,4,15]],
99
+ /* v13 */ [[4,107,0,0],[8,37,1,38],[8,20,4,21],[12,11,4,12]],
100
+ /* v14 */ [[3,115,1,116],[4,40,5,41],[11,16,5,17],[11,12,5,13]],
101
+ /* v15 */ [[5,87,1,88],[5,41,5,42],[5,24,7,25],[11,12,7,13]],
102
+ /* v16 */ [[5,98,1,99],[7,45,3,46],[15,19,2,20],[3,15,13,16]],
103
+ /* v17 */ [[1,107,5,108],[10,46,1,47],[1,22,15,23],[2,14,17,15]],
104
+ /* v18 */ [[5,120,1,121],[9,43,4,44],[17,22,1,23],[2,14,19,15]],
105
+ /* v19 */ [[3,113,4,114],[3,44,11,45],[17,21,4,22],[9,13,16,14]],
106
+ /* v20 */ [[3,107,5,108],[3,41,13,42],[15,24,5,25],[15,15,10,16]],
107
+ /* v21 */ [[4,116,4,117],[17,42,0,0],[17,22,6,23],[19,16,6,17]],
108
+ /* v22 */ [[2,111,7,112],[17,46,0,0],[7,24,16,25],[34,13,0,0]],
109
+ /* v23 */ [[4,121,5,122],[4,47,14,48],[11,24,14,25],[16,15,14,16]],
110
+ /* v24 */ [[6,117,4,118],[6,45,14,46],[11,24,16,25],[30,16,2,17]],
111
+ /* v25 */ [[8,106,4,107],[8,47,13,48],[7,24,22,25],[22,15,13,16]],
112
+ /* v26 */ [[10,114,2,115],[19,46,4,47],[28,22,6,23],[33,16,4,17]],
113
+ /* v27 */ [[8,122,4,123],[22,45,3,46],[8,23,26,24],[12,15,28,16]],
114
+ /* v28 */ [[3,117,10,118],[3,45,23,46],[4,24,31,25],[11,15,31,16]],
115
+ /* v29 */ [[7,116,7,117],[21,45,7,46],[1,23,37,24],[19,15,26,16]],
116
+ /* v30 */ [[5,115,10,116],[19,47,10,48],[15,24,25,25],[23,15,25,16]],
117
+ /* v31 */ [[13,115,3,116],[2,46,29,47],[42,24,1,25],[23,15,28,16]],
118
+ /* v32 */ [[17,115,0,0],[10,46,23,47],[10,24,35,25],[19,15,35,16]],
119
+ /* v33 */ [[17,115,1,116],[14,46,21,47],[29,24,19,25],[11,15,46,16]],
120
+ /* v34 */ [[13,115,6,116],[14,46,23,47],[44,24,7,25],[59,16,1,17]],
121
+ /* v35 */ [[12,121,7,122],[12,47,26,48],[39,24,14,25],[22,15,41,16]],
122
+ /* v36 */ [[6,121,14,122],[6,47,34,48],[46,24,10,25],[2,15,64,16]],
123
+ /* v37 */ [[17,122,4,123],[29,46,14,47],[49,24,10,25],[24,15,46,16]],
124
+ /* v38 */ [[4,122,18,123],[13,46,32,47],[48,24,14,25],[42,15,32,16]],
125
+ /* v39 */ [[20,117,4,118],[40,47,7,48],[43,24,22,25],[10,15,67,16]],
126
+ /* v40 */ [[19,118,6,119],[18,47,31,48],[34,24,34,25],[20,15,61,16]],
127
+ ];
128
+
129
+ /**
130
+ * Alignment-pattern center coordinates per version (empty for v1).
131
+ */
132
+ const ALIGNMENT_COORDS: number[][] = [
133
+ [],
134
+ [6, 18],
135
+ [6, 22],
136
+ [6, 26],
137
+ [6, 30],
138
+ [6, 34],
139
+ [6, 22, 38],
140
+ [6, 24, 42],
141
+ [6, 26, 46],
142
+ [6, 28, 50],
143
+ [6, 30, 54],
144
+ [6, 32, 58],
145
+ [6, 34, 62],
146
+ [6, 26, 46, 66],
147
+ [6, 26, 48, 70],
148
+ [6, 26, 50, 74],
149
+ [6, 30, 54, 78],
150
+ [6, 30, 56, 82],
151
+ [6, 30, 58, 86],
152
+ [6, 34, 62, 90],
153
+ [6, 28, 50, 72, 94],
154
+ [6, 26, 50, 74, 98],
155
+ [6, 30, 54, 78, 102],
156
+ [6, 28, 54, 80, 106],
157
+ [6, 32, 58, 84, 110],
158
+ [6, 30, 58, 86, 114],
159
+ [6, 34, 62, 90, 118],
160
+ [6, 26, 50, 74, 98, 122],
161
+ [6, 30, 54, 78, 102, 126],
162
+ [6, 26, 52, 78, 104, 130],
163
+ [6, 30, 56, 82, 108, 134],
164
+ [6, 34, 60, 86, 112, 138],
165
+ [6, 30, 58, 86, 114, 142],
166
+ [6, 34, 62, 90, 118, 146],
167
+ [6, 30, 54, 78, 102, 126, 150],
168
+ [6, 24, 50, 76, 102, 128, 154],
169
+ [6, 28, 54, 80, 106, 132, 158],
170
+ [6, 32, 58, 84, 110, 136, 162],
171
+ [6, 26, 54, 82, 110, 138, 166],
172
+ [6, 30, 58, 86, 114, 142, 170],
173
+ ];
174
+
175
+ /** Format information bits (15-bit BCH) for each (ecl, mask) pair. */
176
+ const FORMAT_INFO: number[][] = [
177
+ /* L */ [0x77C4, 0x72F3, 0x7DAA, 0x789D, 0x662F, 0x6318, 0x6C41, 0x6976],
178
+ /* M */ [0x5412, 0x5125, 0x5E7C, 0x5B4B, 0x45F9, 0x40CE, 0x4F97, 0x4AA0],
179
+ /* Q */ [0x355F, 0x3068, 0x3F31, 0x3A06, 0x24B4, 0x2183, 0x2EDA, 0x2BED],
180
+ /* H */ [0x1689, 0x13BE, 0x1CE7, 0x19D0, 0x0762, 0x0255, 0x0D0C, 0x083B],
181
+ ];
182
+
183
+ /** Version information bits (18-bit BCH) for versions 7–40. */
184
+ const VERSION_INFO: number[] = [
185
+ 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, 0x0E60D,
186
+ 0x0F928, 0x10B78, 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, 0x168C9,
187
+ 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75,
188
+ 0x1F250, 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, 0x2542E, 0x26A64,
189
+ 0x27541, 0x28C69,
190
+ ];
191
+
192
+ // ---------------------------------------------------------------------------
193
+ // GF(256) arithmetic for Reed-Solomon
194
+ // ---------------------------------------------------------------------------
195
+
196
+ const GF_EXP = new Uint8Array(512);
197
+ const GF_LOG = new Uint8Array(256);
198
+
199
+ (function initGF() {
200
+ let x = 1;
201
+ for (let i = 0; i < 255; i++) {
202
+ GF_EXP[i] = x;
203
+ GF_LOG[x] = i;
204
+ x <<= 1;
205
+ if (x >= 256) x ^= 0x11D; // primitive polynomial
206
+ }
207
+ for (let i = 255; i < 512; i++) {
208
+ GF_EXP[i] = GF_EXP[i - 255];
209
+ }
210
+ })();
211
+
212
+ function gfMul(a: number, b: number): number {
213
+ if (a === 0 || b === 0) return 0;
214
+ return GF_EXP[GF_LOG[a] + GF_LOG[b]];
215
+ }
216
+
217
+ // ---------------------------------------------------------------------------
218
+ // Reed-Solomon EC codeword generation
219
+ // ---------------------------------------------------------------------------
220
+
221
+ function rsGeneratorPoly(degree: number): Uint8Array {
222
+ const gen = new Uint8Array(degree + 1);
223
+ gen[0] = 1;
224
+ for (let i = 0; i < degree; i++) {
225
+ for (let j = degree; j >= 1; j--) {
226
+ gen[j] = gen[j] ^ gfMul(gen[j - 1], GF_EXP[i]);
227
+ }
228
+ // gen[0] stays 1 (leading coeff)
229
+ }
230
+ return gen;
231
+ }
232
+
233
+ function rsEncode(data: Uint8Array, ecCount: number): Uint8Array {
234
+ const gen = rsGeneratorPoly(ecCount);
235
+ const result = new Uint8Array(ecCount);
236
+ for (let i = 0; i < data.length; i++) {
237
+ const coeff = data[i] ^ result[0];
238
+ // shift result left
239
+ for (let j = 0; j < ecCount - 1; j++) {
240
+ result[j] = result[j + 1] ^ gfMul(gen[j + 1], coeff);
241
+ }
242
+ result[ecCount - 1] = gfMul(gen[ecCount], coeff);
243
+ }
244
+ return result;
245
+ }
246
+
247
+ // ---------------------------------------------------------------------------
248
+ // Data encoding (Byte mode only)
249
+ // ---------------------------------------------------------------------------
250
+
251
+ function encodeData(text: string, version: number, ecl: ErrorCorrectionLevel): Uint8Array {
252
+ const eclOrd = EC_ORDINALS[ecl];
253
+ const totalDataCw = DATA_CODEWORDS[version - 1][eclOrd];
254
+ const bytes = new TextEncoder().encode(text);
255
+
256
+ // Build bit stream
257
+ const bits: number[] = [];
258
+ const pushBits = (value: number, length: number) => {
259
+ for (let i = length - 1; i >= 0; i--) {
260
+ bits.push((value >>> i) & 1);
261
+ }
262
+ };
263
+
264
+ // Mode indicator: byte = 0100
265
+ pushBits(0b0100, 4);
266
+
267
+ // Character count indicator
268
+ const ccBits = version <= 9 ? 8 : 16;
269
+ pushBits(bytes.length, ccBits);
270
+
271
+ // Data
272
+ for (const b of bytes) {
273
+ pushBits(b, 8);
274
+ }
275
+
276
+ // Terminator (up to 4 bits of zeros)
277
+ const totalDataBits = totalDataCw * 8;
278
+ const terminatorLen = Math.min(4, totalDataBits - bits.length);
279
+ pushBits(0, terminatorLen);
280
+
281
+ // Pad to byte boundary
282
+ while (bits.length % 8 !== 0) {
283
+ bits.push(0);
284
+ }
285
+
286
+ // Pad codewords
287
+ const padBytes = [0xEC, 0x11];
288
+ let padIdx = 0;
289
+ while (bits.length < totalDataBits) {
290
+ pushBits(padBytes[padIdx], 8);
291
+ padIdx ^= 1;
292
+ }
293
+
294
+ // Convert to byte array
295
+ const codewords = new Uint8Array(totalDataCw);
296
+ for (let i = 0; i < totalDataCw; i++) {
297
+ let byte = 0;
298
+ for (let b = 0; b < 8; b++) {
299
+ byte = (byte << 1) | bits[i * 8 + b];
300
+ }
301
+ codewords[i] = byte;
302
+ }
303
+
304
+ return codewords;
305
+ }
306
+
307
+ // ---------------------------------------------------------------------------
308
+ // Interleave data + EC blocks
309
+ // ---------------------------------------------------------------------------
310
+
311
+ function buildFinalMessage(data: Uint8Array, version: number, ecl: ErrorCorrectionLevel): Uint8Array {
312
+ const eclOrd = EC_ORDINALS[ecl];
313
+ const [g1Count, g1DataCw, g2Count, g2DataCw] = EC_BLOCKS[version - 1][eclOrd];
314
+ const totalCw = TOTAL_CODEWORDS[version - 1];
315
+ const totalBlocks = g1Count + g2Count;
316
+ const ecCwPerBlock = Math.floor((totalCw - DATA_CODEWORDS[version - 1][eclOrd]) / totalBlocks);
317
+
318
+ // Split data into blocks
319
+ const dataBlocks: Uint8Array[] = [];
320
+ const ecBlocks: Uint8Array[] = [];
321
+ let offset = 0;
322
+
323
+ for (let i = 0; i < g1Count; i++) {
324
+ const block = data.slice(offset, offset + g1DataCw);
325
+ dataBlocks.push(block);
326
+ ecBlocks.push(rsEncode(block, ecCwPerBlock));
327
+ offset += g1DataCw;
328
+ }
329
+ for (let i = 0; i < g2Count; i++) {
330
+ const block = data.slice(offset, offset + g2DataCw);
331
+ dataBlocks.push(block);
332
+ ecBlocks.push(rsEncode(block, ecCwPerBlock));
333
+ offset += g2DataCw;
334
+ }
335
+
336
+ // Interleave data codewords
337
+ const result: number[] = [];
338
+ const maxDataCw = Math.max(g1DataCw, g2DataCw);
339
+ for (let i = 0; i < maxDataCw; i++) {
340
+ for (let j = 0; j < totalBlocks; j++) {
341
+ if (i < dataBlocks[j].length) {
342
+ result.push(dataBlocks[j][i]);
343
+ }
344
+ }
345
+ }
346
+
347
+ // Interleave EC codewords
348
+ for (let i = 0; i < ecCwPerBlock; i++) {
349
+ for (let j = 0; j < totalBlocks; j++) {
350
+ result.push(ecBlocks[j][i]);
351
+ }
352
+ }
353
+
354
+ return new Uint8Array(result);
355
+ }
356
+
357
+ // ---------------------------------------------------------------------------
358
+ // QR matrix construction
359
+ // ---------------------------------------------------------------------------
360
+
361
+ /** Module size = 4 * version + 17 */
362
+ function getModuleCount(version: number): number {
363
+ return version * 4 + 17;
364
+ }
365
+
366
+ /** Create a blank matrix (-1 = unset). */
367
+ function createMatrix(size: number): number[][] {
368
+ return Array.from({ length: size }, () => Array(size).fill(-1));
369
+ }
370
+
371
+ function setModule(matrix: number[][], row: number, col: number, value: number): void {
372
+ if (row >= 0 && row < matrix.length && col >= 0 && col < matrix.length) {
373
+ matrix[row][col] = value;
374
+ }
375
+ }
376
+
377
+ /** Place a finder pattern with its separator. */
378
+ function placeFinderPattern(matrix: number[][], row: number, col: number): void {
379
+ for (let r = -1; r <= 7; r++) {
380
+ for (let c = -1; c <= 7; c++) {
381
+ const isPattern = r >= 0 && r <= 6 && c >= 0 && c <= 6;
382
+ let value = 0;
383
+ if (isPattern) {
384
+ if (r === 0 || r === 6 || c === 0 || c === 6 ||
385
+ (r >= 2 && r <= 4 && c >= 2 && c <= 4)) {
386
+ value = 1;
387
+ }
388
+ }
389
+ setModule(matrix, row + r, col + c, value);
390
+ }
391
+ }
392
+ }
393
+
394
+ /** Place alignment patterns. */
395
+ function placeAlignmentPatterns(matrix: number[][], version: number): void {
396
+ if (version < 2) return;
397
+ const coords = ALIGNMENT_COORDS[version - 1];
398
+ for (const r of coords) {
399
+ for (const c of coords) {
400
+ // Skip if overlapping finder patterns
401
+ if (matrix[r][c] !== -1) continue;
402
+ for (let dr = -2; dr <= 2; dr++) {
403
+ for (let dc = -2; dc <= 2; dc++) {
404
+ const value = (Math.abs(dr) === 2 || Math.abs(dc) === 2 ||
405
+ (dr === 0 && dc === 0)) ? 1 : 0;
406
+ setModule(matrix, r + dr, c + dc, value);
407
+ }
408
+ }
409
+ }
410
+ }
411
+ }
412
+
413
+ /** Place timing patterns. */
414
+ function placeTimingPatterns(matrix: number[][]): void {
415
+ const size = matrix.length;
416
+ for (let i = 8; i < size - 8; i++) {
417
+ if (matrix[6][i] === -1) matrix[6][i] = (i + 1) % 2;
418
+ if (matrix[i][6] === -1) matrix[i][6] = (i + 1) % 2;
419
+ }
420
+ }
421
+
422
+ /** Reserve format info areas (filled later). */
423
+ function reserveFormatAreas(matrix: number[][]): void {
424
+ const size = matrix.length;
425
+ // Around top-left finder
426
+ for (let i = 0; i <= 8; i++) {
427
+ if (matrix[8][i] === -1) matrix[8][i] = 0;
428
+ if (matrix[i][8] === -1) matrix[i][8] = 0;
429
+ }
430
+ // Around top-right finder
431
+ for (let i = 0; i <= 7; i++) {
432
+ if (matrix[8][size - 1 - i] === -1) matrix[8][size - 1 - i] = 0;
433
+ }
434
+ // Around bottom-left finder
435
+ for (let i = 0; i <= 7; i++) {
436
+ if (matrix[size - 1 - i][8] === -1) matrix[size - 1 - i][8] = 0;
437
+ }
438
+ // Dark module
439
+ matrix[size - 8][8] = 1;
440
+ }
441
+
442
+ /** Reserve version info areas (versions >= 7). */
443
+ function reserveVersionAreas(matrix: number[][], version: number): void {
444
+ if (version < 7) return;
445
+ const size = matrix.length;
446
+ for (let i = 0; i < 6; i++) {
447
+ for (let j = 0; j < 3; j++) {
448
+ if (matrix[i][size - 11 + j] === -1) matrix[i][size - 11 + j] = 0;
449
+ if (matrix[size - 11 + j][i] === -1) matrix[size - 11 + j][i] = 0;
450
+ }
451
+ }
452
+ }
453
+
454
+ /** Place data bits in the matrix using the zigzag pattern. */
455
+ function placeDataBits(matrix: number[][], data: Uint8Array): void {
456
+ const size = matrix.length;
457
+ let bitIndex = 0;
458
+ const totalBits = data.length * 8;
459
+ let upward = true;
460
+
461
+ for (let right = size - 1; right >= 1; right -= 2) {
462
+ // Skip timing pattern column
463
+ if (right === 6) right = 5;
464
+
465
+ for (let vert = 0; vert < size; vert++) {
466
+ const row = upward ? size - 1 - vert : vert;
467
+ for (let colOffset = 0; colOffset <= 1; colOffset++) {
468
+ const col = right - colOffset;
469
+ if (matrix[row][col] !== -1) continue;
470
+ if (bitIndex < totalBits) {
471
+ const byteIdx = bitIndex >>> 3;
472
+ const bitIdx = 7 - (bitIndex & 7);
473
+ matrix[row][col] = (data[byteIdx] >>> bitIdx) & 1;
474
+ bitIndex++;
475
+ } else {
476
+ matrix[row][col] = 0;
477
+ }
478
+ }
479
+ }
480
+ upward = !upward;
481
+ }
482
+ }
483
+
484
+ // ---------------------------------------------------------------------------
485
+ // Masking
486
+ // ---------------------------------------------------------------------------
487
+
488
+ type MaskFn = (row: number, col: number) => boolean;
489
+
490
+ const MASK_FUNCTIONS: MaskFn[] = [
491
+ (r, c) => (r + c) % 2 === 0,
492
+ (r, _c) => r % 2 === 0,
493
+ (_r, c) => c % 3 === 0,
494
+ (r, c) => (r + c) % 3 === 0,
495
+ (r, c) => (Math.floor(r / 2) + Math.floor(c / 3)) % 2 === 0,
496
+ (r, c) => ((r * c) % 2 + (r * c) % 3) === 0,
497
+ (r, c) => ((r * c) % 2 + (r * c) % 3) % 2 === 0,
498
+ (r, c) => ((r + c) % 2 + (r * c) % 3) % 2 === 0,
499
+ ];
500
+
501
+ /** Check if a module is a function pattern (not data). */
502
+ function isFunctionModule(matrix: number[][], reserved: number[][], row: number, col: number): boolean {
503
+ return reserved[row][col] !== -1;
504
+ }
505
+
506
+ function applyMask(matrix: number[][], reserved: number[][], maskIdx: number): number[][] {
507
+ const size = matrix.length;
508
+ const result = matrix.map(row => [...row]);
509
+ const fn = MASK_FUNCTIONS[maskIdx];
510
+ for (let r = 0; r < size; r++) {
511
+ for (let c = 0; c < size; c++) {
512
+ if (!isFunctionModule(result, reserved, r, c) && fn(r, c)) {
513
+ result[r][c] ^= 1;
514
+ }
515
+ }
516
+ }
517
+ return result;
518
+ }
519
+
520
+ // ---------------------------------------------------------------------------
521
+ // Format & version info writing
522
+ // ---------------------------------------------------------------------------
523
+
524
+ function writeFormatInfo(matrix: number[][], ecl: ErrorCorrectionLevel, maskIdx: number): void {
525
+ const eclOrd = EC_ORDINALS[ecl];
526
+ const bits = FORMAT_INFO[eclOrd][maskIdx];
527
+ const size = matrix.length;
528
+
529
+ for (let i = 0; i <= 5; i++) {
530
+ matrix[8][i] = (bits >>> (14 - i)) & 1;
531
+ }
532
+ matrix[8][7] = (bits >>> 8) & 1;
533
+ matrix[8][8] = (bits >>> 7) & 1;
534
+ matrix[7][8] = (bits >>> 6) & 1;
535
+ for (let i = 0; i <= 5; i++) {
536
+ matrix[5 - i][8] = (bits >>> (i)) & 1;
537
+ }
538
+
539
+ for (let i = 0; i <= 7; i++) {
540
+ matrix[8][size - 1 - i] = (bits >>> i) & 1;
541
+ }
542
+ for (let i = 0; i <= 6; i++) {
543
+ matrix[size - 1 - i][8] = (bits >>> (14 - i)) & 1;
544
+ }
545
+
546
+ matrix[size - 8][8] = 1; // dark module
547
+ }
548
+
549
+ function writeVersionInfo(matrix: number[][], version: number): void {
550
+ if (version < 7) return;
551
+ const bits = VERSION_INFO[version - 7];
552
+ const size = matrix.length;
553
+ for (let i = 0; i < 6; i++) {
554
+ for (let j = 0; j < 3; j++) {
555
+ const bitIdx = i * 3 + j;
556
+ const bit = (bits >>> bitIdx) & 1;
557
+ matrix[i][size - 11 + j] = bit;
558
+ matrix[size - 11 + j][i] = bit;
559
+ }
560
+ }
561
+ }
562
+
563
+ // ---------------------------------------------------------------------------
564
+ // Penalty scoring
565
+ // ---------------------------------------------------------------------------
566
+
567
+ function penaltyScore(matrix: number[][]): number {
568
+ const size = matrix.length;
569
+ let score = 0;
570
+
571
+ // Rule 1: 5+ consecutive same-color modules in row/col
572
+ for (let r = 0; r < size; r++) {
573
+ let count = 1;
574
+ for (let c = 1; c < size; c++) {
575
+ if (matrix[r][c] === matrix[r][c - 1]) {
576
+ count++;
577
+ } else {
578
+ if (count >= 5) score += count - 2;
579
+ count = 1;
580
+ }
581
+ }
582
+ if (count >= 5) score += count - 2;
583
+ }
584
+ for (let c = 0; c < size; c++) {
585
+ let count = 1;
586
+ for (let r = 1; r < size; r++) {
587
+ if (matrix[r][c] === matrix[r - 1][c]) {
588
+ count++;
589
+ } else {
590
+ if (count >= 5) score += count - 2;
591
+ count = 1;
592
+ }
593
+ }
594
+ if (count >= 5) score += count - 2;
595
+ }
596
+
597
+ // Rule 2: 2x2 blocks of same color
598
+ for (let r = 0; r < size - 1; r++) {
599
+ for (let c = 0; c < size - 1; c++) {
600
+ const val = matrix[r][c];
601
+ if (val === matrix[r][c + 1] && val === matrix[r + 1][c] && val === matrix[r + 1][c + 1]) {
602
+ score += 3;
603
+ }
604
+ }
605
+ }
606
+
607
+ // Rule 3: Finder-like patterns
608
+ const pattern1 = [1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0];
609
+ const pattern2 = [0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1];
610
+ for (let r = 0; r < size; r++) {
611
+ for (let c = 0; c <= size - 11; c++) {
612
+ let match1 = true;
613
+ let match2 = true;
614
+ for (let i = 0; i < 11; i++) {
615
+ if (matrix[r][c + i] !== pattern1[i]) match1 = false;
616
+ if (matrix[r][c + i] !== pattern2[i]) match2 = false;
617
+ }
618
+ if (match1 || match2) score += 40;
619
+ }
620
+ }
621
+ for (let c = 0; c < size; c++) {
622
+ for (let r = 0; r <= size - 11; r++) {
623
+ let match1 = true;
624
+ let match2 = true;
625
+ for (let i = 0; i < 11; i++) {
626
+ if (matrix[r + i][c] !== pattern1[i]) match1 = false;
627
+ if (matrix[r + i][c] !== pattern2[i]) match2 = false;
628
+ }
629
+ if (match1 || match2) score += 40;
630
+ }
631
+ }
632
+
633
+ // Rule 4: Proportion of dark modules
634
+ let dark = 0;
635
+ for (let r = 0; r < size; r++) {
636
+ for (let c = 0; c < size; c++) {
637
+ if (matrix[r][c] === 1) dark++;
638
+ }
639
+ }
640
+ const total = size * size;
641
+ const percent = (dark / total) * 100;
642
+ const prev5 = Math.floor(percent / 5) * 5;
643
+ const next5 = prev5 + 5;
644
+ score += Math.min(Math.abs(prev5 - 50) / 5, Math.abs(next5 - 50) / 5) * 10;
645
+
646
+ return score;
647
+ }
648
+
649
+ // ---------------------------------------------------------------------------
650
+ // Public API
651
+ // ---------------------------------------------------------------------------
652
+
653
+ /**
654
+ * Find the minimum version that can hold the given data.
655
+ */
656
+ function findMinVersion(text: string, ecl: ErrorCorrectionLevel): number {
657
+ const bytes = new TextEncoder().encode(text);
658
+ const dataLen = bytes.length;
659
+ const eclOrd = EC_ORDINALS[ecl];
660
+
661
+ for (let v = 1; v <= 40; v++) {
662
+ const ccBits = v <= 9 ? 8 : 16;
663
+ const totalBits = 4 + ccBits + dataLen * 8;
664
+ const capacity = DATA_CODEWORDS[v - 1][eclOrd] * 8;
665
+ if (totalBits <= capacity) return v;
666
+ }
667
+ throw new Error('Data too long for any QR version');
668
+ }
669
+
670
+ /**
671
+ * Generate a QR code matrix from a string.
672
+ *
673
+ * @param text The text to encode.
674
+ * @param ecl Error-correction level (L, M, Q, H).
675
+ * @returns A 2-D boolean-like matrix where `1` = dark module.
676
+ */
677
+ export function generateQR(text: string, ecl: ErrorCorrectionLevel = 'H'): number[][] {
678
+ if (!text) {
679
+ // Return a minimal empty 21x21 (version 1) blank grid
680
+ return Array.from({ length: 21 }, () => Array(21).fill(0));
681
+ }
682
+
683
+ const version = findMinVersion(text, ecl);
684
+ const moduleCount = getModuleCount(version);
685
+
686
+ // 1. Build function-pattern matrix (reserved areas)
687
+ const reserved = createMatrix(moduleCount);
688
+ placeFinderPattern(reserved, 0, 0);
689
+ placeFinderPattern(reserved, 0, moduleCount - 7);
690
+ placeFinderPattern(reserved, moduleCount - 7, 0);
691
+ placeAlignmentPatterns(reserved, version);
692
+ placeTimingPatterns(reserved);
693
+ reserveFormatAreas(reserved);
694
+ reserveVersionAreas(reserved, version);
695
+
696
+ // 2. Build actual matrix with function patterns
697
+ const matrix = createMatrix(moduleCount);
698
+ placeFinderPattern(matrix, 0, 0);
699
+ placeFinderPattern(matrix, 0, moduleCount - 7);
700
+ placeFinderPattern(matrix, moduleCount - 7, 0);
701
+ placeAlignmentPatterns(matrix, version);
702
+ placeTimingPatterns(matrix);
703
+ reserveFormatAreas(matrix);
704
+ reserveVersionAreas(matrix, version);
705
+
706
+ // 3. Encode & place data
707
+ const dataCw = encodeData(text, version, ecl);
708
+ const finalMsg = buildFinalMessage(dataCw, version, ecl);
709
+ placeDataBits(matrix, finalMsg);
710
+
711
+ // 4. Try all 8 masks, pick the best
712
+ let bestMask = 0;
713
+ let bestScore = Infinity;
714
+ let bestMatrix = matrix;
715
+
716
+ for (let mask = 0; mask < 8; mask++) {
717
+ const candidate = applyMask(matrix, reserved, mask);
718
+ writeFormatInfo(candidate, ecl, mask);
719
+ writeVersionInfo(candidate, version);
720
+ const score = penaltyScore(candidate);
721
+ if (score < bestScore) {
722
+ bestScore = score;
723
+ bestMask = mask;
724
+ bestMatrix = candidate;
725
+ }
726
+ }
727
+
728
+ // Re-apply best mask (already stored)
729
+ writeFormatInfo(bestMatrix, ecl, bestMask);
730
+ writeVersionInfo(bestMatrix, version);
731
+
732
+ return bestMatrix;
733
+ }