lcp 0.1.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 (1676) hide show
  1. checksums.yaml +7 -0
  2. data/.claude/skills/lcp-custom-field/SKILL.md +205 -0
  3. data/.claude/skills/lcp-getting-started/SKILL.md +332 -0
  4. data/.claude/skills/lcp-host-binding/SKILL.md +287 -0
  5. data/.claude/skills/lcp-model/SKILL.md +185 -0
  6. data/.claude/skills/lcp-permissions/SKILL.md +176 -0
  7. data/.claude/skills/lcp-presenter/SKILL.md +194 -0
  8. data/.claude/skills/lcp-workflow/SKILL.md +281 -0
  9. data/CHANGELOG.md +69 -0
  10. data/MIT-LICENSE +20 -0
  11. data/README.md +28 -0
  12. data/Rakefile +17 -0
  13. data/app/assets/javascripts/lcp_ruby/application.js +58 -0
  14. data/app/assets/javascripts/lcp_ruby/controllers/advanced_filter_controller.js +1521 -0
  15. data/app/assets/javascripts/lcp_ruby/controllers/approval_actions_controller.js +24 -0
  16. data/app/assets/javascripts/lcp_ruby/controllers/array_input_controller.js +156 -0
  17. data/app/assets/javascripts/lcp_ruby/controllers/batch_select_controller.js +405 -0
  18. data/app/assets/javascripts/lcp_ruby/controllers/cascading_selects_controller.js +436 -0
  19. data/app/assets/javascripts/lcp_ruby/controllers/char_counter_controller.js +28 -0
  20. data/app/assets/javascripts/lcp_ruby/controllers/clipboard_controller.js +62 -0
  21. data/app/assets/javascripts/lcp_ruby/controllers/conditional_rendering_controller.js +178 -0
  22. data/app/assets/javascripts/lcp_ruby/controllers/confirm_dialog_controller.js +131 -0
  23. data/app/assets/javascripts/lcp_ruby/controllers/custom_fields_manage_controller.js +80 -0
  24. data/app/assets/javascripts/lcp_ruby/controllers/dialog_controller.js +421 -0
  25. data/app/assets/javascripts/lcp_ruby/controllers/dialog_nested_controller.js +182 -0
  26. data/app/assets/javascripts/lcp_ruby/controllers/direct_upload_controller.js +100 -0
  27. data/app/assets/javascripts/lcp_ruby/controllers/drawer_controller.js +205 -0
  28. data/app/assets/javascripts/lcp_ruby/controllers/dropdown_controller.js +160 -0
  29. data/app/assets/javascripts/lcp_ruby/controllers/export_dialog_controller.js +15 -0
  30. data/app/assets/javascripts/lcp_ruby/controllers/field_picker_controller.js +290 -0
  31. data/app/assets/javascripts/lcp_ruby/controllers/file_upload_controller.js +135 -0
  32. data/app/assets/javascripts/lcp_ruby/controllers/filter_auto_submit_controller.js +46 -0
  33. data/app/assets/javascripts/lcp_ruby/controllers/filter_dirty_controller.js +94 -0
  34. data/app/assets/javascripts/lcp_ruby/controllers/form_actions_controller.js +68 -0
  35. data/app/assets/javascripts/lcp_ruby/controllers/form_handling_controller.js +67 -0
  36. data/app/assets/javascripts/lcp_ruby/controllers/import_dialog_controller.js +142 -0
  37. data/app/assets/javascripts/lcp_ruby/controllers/import_mapper_controller.js +322 -0
  38. data/app/assets/javascripts/lcp_ruby/controllers/index_sortable_controller.js +388 -0
  39. data/app/assets/javascripts/lcp_ruby/controllers/inline_create_controller.js +137 -0
  40. data/app/assets/javascripts/lcp_ruby/controllers/kanban_board_controller.js +290 -0
  41. data/app/assets/javascripts/lcp_ruby/controllers/menu_controller.js +19 -0
  42. data/app/assets/javascripts/lcp_ruby/controllers/nested_forms_controller.js +261 -0
  43. data/app/assets/javascripts/lcp_ruby/controllers/responsive_sidebar_controller.js +161 -0
  44. data/app/assets/javascripts/lcp_ruby/controllers/responsive_top_nav_controller.js +394 -0
  45. data/app/assets/javascripts/lcp_ruby/controllers/saved_filters_controller.js +129 -0
  46. data/app/assets/javascripts/lcp_ruby/controllers/search_controller.js +82 -0
  47. data/app/assets/javascripts/lcp_ruby/controllers/selection_controller.js +33 -0
  48. data/app/assets/javascripts/lcp_ruby/controllers/sidebar_controller.js +83 -0
  49. data/app/assets/javascripts/lcp_ruby/controllers/sidebar_toggle_controller.js +66 -0
  50. data/app/assets/javascripts/lcp_ruby/controllers/slider_controller.js +26 -0
  51. data/app/assets/javascripts/lcp_ruby/controllers/submenu_controller.js +55 -0
  52. data/app/assets/javascripts/lcp_ruby/controllers/tom_select_controller.js +168 -0
  53. data/app/assets/javascripts/lcp_ruby/controllers/tree_index_controller.js +106 -0
  54. data/app/assets/javascripts/lcp_ruby/controllers/tree_reparent_controller.js +182 -0
  55. data/app/assets/javascripts/lcp_ruby/controllers/tree_select_controller.js +119 -0
  56. data/app/assets/javascripts/lcp_ruby/controllers/ui_components_controller.js +135 -0
  57. data/app/assets/javascripts/lcp_ruby/controllers/zone_tabs_controller.js +66 -0
  58. data/app/assets/javascripts/lcp_ruby/dev_toolbar.js +494 -0
  59. data/app/assets/javascripts/lcp_ruby/i18n.js.erb +29 -0
  60. data/app/assets/javascripts/lcp_ruby/lucide_init.js +24 -0
  61. data/app/assets/javascripts/lcp_ruby/stimulus_bootstrap.js +7 -0
  62. data/app/assets/javascripts/lcp_ruby/utils.js +119 -0
  63. data/app/assets/javascripts/lcp_ruby/xhr_fetch.js +411 -0
  64. data/app/assets/stylesheets/lcp_ruby/application.css +1940 -0
  65. data/app/assets/stylesheets/lcp_ruby/dev_toolbar.css +355 -0
  66. data/app/controllers/concerns/lcp_ruby/dialog_rendering.rb +167 -0
  67. data/app/controllers/concerns/lcp_ruby/form_action_execution.rb +249 -0
  68. data/app/controllers/concerns/lcp_ruby/page_authorization.rb +105 -0
  69. data/app/controllers/concerns/lcp_ruby/zone_resolution.rb +199 -0
  70. data/app/controllers/lcp_ruby/actions_controller.rb +481 -0
  71. data/app/controllers/lcp_ruby/application_controller.rb +59 -0
  72. data/app/controllers/lcp_ruby/approval_tasks_controller.rb +98 -0
  73. data/app/controllers/lcp_ruby/auth/base_controller.rb +58 -0
  74. data/app/controllers/lcp_ruby/auth/callbacks_controller.rb +103 -0
  75. data/app/controllers/lcp_ruby/auth/passwords_controller.rb +15 -0
  76. data/app/controllers/lcp_ruby/auth/registrations_controller.rb +37 -0
  77. data/app/controllers/lcp_ruby/auth/sessions_controller.rb +112 -0
  78. data/app/controllers/lcp_ruby/custom_fields_controller.rb +370 -0
  79. data/app/controllers/lcp_ruby/dev_toolbar_controller.rb +197 -0
  80. data/app/controllers/lcp_ruby/dialogs_controller.rb +199 -0
  81. data/app/controllers/lcp_ruby/health_controller.rb +23 -0
  82. data/app/controllers/lcp_ruby/impersonation_controller.rb +32 -0
  83. data/app/controllers/lcp_ruby/landing_controller.rb +49 -0
  84. data/app/controllers/lcp_ruby/metrics_controller.rb +17 -0
  85. data/app/controllers/lcp_ruby/resources_controller.rb +2218 -0
  86. data/app/controllers/lcp_ruby/saved_filters_controller.rb +221 -0
  87. data/app/helpers/lcp_ruby/condition_helper.rb +87 -0
  88. data/app/helpers/lcp_ruby/dashboard_helper.rb +45 -0
  89. data/app/helpers/lcp_ruby/dev_toolbar_helper.rb +17 -0
  90. data/app/helpers/lcp_ruby/dialog_helper.rb +27 -0
  91. data/app/helpers/lcp_ruby/display/card_helper.rb +317 -0
  92. data/app/helpers/lcp_ruby/display_helper.rb +63 -0
  93. data/app/helpers/lcp_ruby/display_template_helper.rb +100 -0
  94. data/app/helpers/lcp_ruby/form_helper.rb +1020 -0
  95. data/app/helpers/lcp_ruby/grouped_query_helper.rb +107 -0
  96. data/app/helpers/lcp_ruby/i18n_payload_helper.rb +197 -0
  97. data/app/helpers/lcp_ruby/layout_helper.rb +832 -0
  98. data/app/helpers/lcp_ruby/link_through_helper.rb +29 -0
  99. data/app/helpers/lcp_ruby/oidc_button_helper.rb +59 -0
  100. data/app/helpers/lcp_ruby/search_helper.rb +31 -0
  101. data/app/helpers/lcp_ruby/tree_helper.rb +140 -0
  102. data/app/helpers/lcp_ruby/view_slot_helper.rb +33 -0
  103. data/app/models/lcp_ruby/user.rb +61 -0
  104. data/app/views/layouts/lcp_ruby/application.html.erb +168 -0
  105. data/app/views/layouts/lcp_ruby/auth.html.erb +170 -0
  106. data/app/views/lcp_ruby/auth/callbacks/failure.html.erb +18 -0
  107. data/app/views/lcp_ruby/auth/mailer/reset_password_instructions.html.erb +9 -0
  108. data/app/views/lcp_ruby/auth/passwords/edit.html.erb +34 -0
  109. data/app/views/lcp_ruby/auth/passwords/new.html.erb +24 -0
  110. data/app/views/lcp_ruby/auth/registrations/edit.html.erb +48 -0
  111. data/app/views/lcp_ruby/auth/registrations/new.html.erb +46 -0
  112. data/app/views/lcp_ruby/auth/sessions/new.html.erb +55 -0
  113. data/app/views/lcp_ruby/auth/shared/_links.html.erb +13 -0
  114. data/app/views/lcp_ruby/custom_fields/_manage_row.html.erb +82 -0
  115. data/app/views/lcp_ruby/custom_fields/manage.html.erb +47 -0
  116. data/app/views/lcp_ruby/dialogs/_dialog_composite_frame.html.erb +87 -0
  117. data/app/views/lcp_ruby/dialogs/_dialog_frame.html.erb +60 -0
  118. data/app/views/lcp_ruby/dialogs/_dialog_show_frame.html.erb +14 -0
  119. data/app/views/lcp_ruby/dialogs/_show_secret.html.erb +10 -0
  120. data/app/views/lcp_ruby/dialogs/_success.html.erb +1 -0
  121. data/app/views/lcp_ruby/errors/not_found.html.erb +5 -0
  122. data/app/views/lcp_ruby/menu_renderers/_user_menu.html.erb +51 -0
  123. data/app/views/lcp_ruby/menu_renderers/_user_menu_panel.html.erb +32 -0
  124. data/app/views/lcp_ruby/navigation/_auto_top.html.erb +16 -0
  125. data/app/views/lcp_ruby/navigation/_both_sidebar.html.erb +1 -0
  126. data/app/views/lcp_ruby/navigation/_both_top.html.erb +1 -0
  127. data/app/views/lcp_ruby/navigation/_impersonation_banner.html.erb +14 -0
  128. data/app/views/lcp_ruby/navigation/_item_content.html.erb +23 -0
  129. data/app/views/lcp_ruby/navigation/_link_or_button.html.erb +51 -0
  130. data/app/views/lcp_ruby/navigation/_mobile_header.html.erb +23 -0
  131. data/app/views/lcp_ruby/navigation/_panel_item.html.erb +32 -0
  132. data/app/views/lcp_ruby/navigation/_sidebar.html.erb +38 -0
  133. data/app/views/lcp_ruby/navigation/_sidebar_item.html.erb +38 -0
  134. data/app/views/lcp_ruby/navigation/_sidebar_toggle.html.erb +32 -0
  135. data/app/views/lcp_ruby/navigation/_top.html.erb +26 -0
  136. data/app/views/lcp_ruby/navigation/_top_item.html.erb +112 -0
  137. data/app/views/lcp_ruby/navigation/_widget_item.html.erb +14 -0
  138. data/app/views/lcp_ruby/resources/_action_button.html.erb +138 -0
  139. data/app/views/lcp_ruby/resources/_advanced_filter.html.erb +55 -0
  140. data/app/views/lcp_ruby/resources/_api_status_banner.html.erb +11 -0
  141. data/app/views/lcp_ruby/resources/_association_list.html.erb +132 -0
  142. data/app/views/lcp_ruby/resources/_audit_history.html.erb +66 -0
  143. data/app/views/lcp_ruby/resources/_batch_toolbar.html.erb +54 -0
  144. data/app/views/lcp_ruby/resources/_filter_form.html.erb +57 -0
  145. data/app/views/lcp_ruby/resources/_form.html.erb +73 -0
  146. data/app/views/lcp_ruby/resources/_form_action_button.html.erb +20 -0
  147. data/app/views/lcp_ruby/resources/_form_action_dropdown_item.html.erb +17 -0
  148. data/app/views/lcp_ruby/resources/_form_actions.html.erb +38 -0
  149. data/app/views/lcp_ruby/resources/_form_section.html.erb +235 -0
  150. data/app/views/lcp_ruby/resources/_grid_page.html.erb +17 -0
  151. data/app/views/lcp_ruby/resources/_grouped_index.html.erb +61 -0
  152. data/app/views/lcp_ruby/resources/_inline_create_form.html.erb +50 -0
  153. data/app/views/lcp_ruby/resources/_json_items_list.html.erb +77 -0
  154. data/app/views/lcp_ruby/resources/_json_nested_fields.html.erb +30 -0
  155. data/app/views/lcp_ruby/resources/_kanban_card.html.erb +31 -0
  156. data/app/views/lcp_ruby/resources/_kanban_card_body.html.erb +17 -0
  157. data/app/views/lcp_ruby/resources/_kanban_column.html.erb +33 -0
  158. data/app/views/lcp_ruby/resources/_kanban_column_header.html.erb +10 -0
  159. data/app/views/lcp_ruby/resources/_kanban_index.html.erb +17 -0
  160. data/app/views/lcp_ruby/resources/_nested_field_cell.html.erb +33 -0
  161. data/app/views/lcp_ruby/resources/_nested_fields.html.erb +26 -0
  162. data/app/views/lcp_ruby/resources/_nested_row_content.html.erb +65 -0
  163. data/app/views/lcp_ruby/resources/_scope_filters.html.erb +71 -0
  164. data/app/views/lcp_ruby/resources/_semantic_index_page.html.erb +162 -0
  165. data/app/views/lcp_ruby/resources/_semantic_page.html.erb +121 -0
  166. data/app/views/lcp_ruby/resources/_show_sections.html.erb +128 -0
  167. data/app/views/lcp_ruby/resources/_table_index.html.erb +169 -0
  168. data/app/views/lcp_ruby/resources/_tile_card.html.erb +26 -0
  169. data/app/views/lcp_ruby/resources/_tile_card_body.html.erb +19 -0
  170. data/app/views/lcp_ruby/resources/_tiles_index.html.erb +15 -0
  171. data/app/views/lcp_ruby/resources/_transition_button.html.erb +33 -0
  172. data/app/views/lcp_ruby/resources/_tree_index.html.erb +61 -0
  173. data/app/views/lcp_ruby/resources/_view_switcher.html.erb +24 -0
  174. data/app/views/lcp_ruby/resources/edit.html.erb +9 -0
  175. data/app/views/lcp_ruby/resources/index.html.erb +80 -0
  176. data/app/views/lcp_ruby/resources/new.html.erb +9 -0
  177. data/app/views/lcp_ruby/resources/show.html.erb +37 -0
  178. data/app/views/lcp_ruby/shared/_breadcrumbs.html.erb +15 -0
  179. data/app/views/lcp_ruby/shared/_custom_partial_error.html.erb +3 -0
  180. data/app/views/lcp_ruby/shared/_flash_messages.html.erb +19 -0
  181. data/app/views/lcp_ruby/slots/index/_advanced_filter.html.erb +3 -0
  182. data/app/views/lcp_ruby/slots/index/_collection_actions.html.erb +50 -0
  183. data/app/views/lcp_ruby/slots/index/_manage_all.html.erb +4 -0
  184. data/app/views/lcp_ruby/slots/index/_pagination_footer.html.erb +71 -0
  185. data/app/views/lcp_ruby/slots/index/_predefined_filters.html.erb +8 -0
  186. data/app/views/lcp_ruby/slots/index/_saved_filters.html.erb +87 -0
  187. data/app/views/lcp_ruby/slots/index/_search.html.erb +52 -0
  188. data/app/views/lcp_ruby/slots/index/_search_parameter.html.erb +72 -0
  189. data/app/views/lcp_ruby/slots/index/_sort_dropdown.html.erb +21 -0
  190. data/app/views/lcp_ruby/slots/index/_summary_bar.html.erb +22 -0
  191. data/app/views/lcp_ruby/slots/index/_view_switcher.html.erb +1 -0
  192. data/app/views/lcp_ruby/slots/show/_approval_status.html.erb +8 -0
  193. data/app/views/lcp_ruby/slots/show/_back_to_list.html.erb +1 -0
  194. data/app/views/lcp_ruby/slots/show/_copy_url.html.erb +5 -0
  195. data/app/views/lcp_ruby/slots/show/_single_actions.html.erb +4 -0
  196. data/app/views/lcp_ruby/slots/show/_view_switcher.html.erb +1 -0
  197. data/app/views/lcp_ruby/widgets/_approval_status.html.erb +150 -0
  198. data/app/views/lcp_ruby/widgets/_chart.html.erb +36 -0
  199. data/app/views/lcp_ruby/widgets/_embed.html.erb +13 -0
  200. data/app/views/lcp_ruby/widgets/_kpi_card.html.erb +29 -0
  201. data/app/views/lcp_ruby/widgets/_list.html.erb +17 -0
  202. data/app/views/lcp_ruby/widgets/_presenter_zone.html.erb +84 -0
  203. data/app/views/lcp_ruby/widgets/_record_show_zone.html.erb +11 -0
  204. data/app/views/lcp_ruby/widgets/_text.html.erb +3 -0
  205. data/app/views/lcp_ruby/widgets/_workflow_graph.html.erb +32 -0
  206. data/app/views/lcp_ruby/zones/_custom_zone.html.erb +16 -0
  207. data/app/views/lcp_ruby/zones/_error.html.erb +5 -0
  208. data/app/views/lcp_ruby/zones/_zone_frame.html.erb +25 -0
  209. data/app/views/lcp_ruby/zones/_zone_search.html.erb +20 -0
  210. data/config/locales/cs.yml +859 -0
  211. data/config/locales/en.yml +731 -0
  212. data/config/routes.rb +119 -0
  213. data/docs/README.md +225 -0
  214. data/docs/architecture.md +212 -0
  215. data/docs/feature-catalog.md +763 -0
  216. data/docs/feature-catalog.yml +20911 -0
  217. data/docs/getting-started.md +1187 -0
  218. data/docs/guides/action-buttons.md +537 -0
  219. data/docs/guides/adding-locale.md +353 -0
  220. data/docs/guides/api-backed-models.md +478 -0
  221. data/docs/guides/attachments.md +399 -0
  222. data/docs/guides/auditing.md +333 -0
  223. data/docs/guides/batch-actions.md +342 -0
  224. data/docs/guides/composite-pages.md +1290 -0
  225. data/docs/guides/computed-fields.md +350 -0
  226. data/docs/guides/conditional-rendering.md +832 -0
  227. data/docs/guides/custom-actions.md +238 -0
  228. data/docs/guides/custom-fields.md +439 -0
  229. data/docs/guides/custom-renderers.md +234 -0
  230. data/docs/guides/custom-types.md +274 -0
  231. data/docs/guides/dashboards.md +504 -0
  232. data/docs/guides/debugging/README.md +38 -0
  233. data/docs/guides/debugging/controllers.md +147 -0
  234. data/docs/guides/debugging/data.md +165 -0
  235. data/docs/guides/debugging/metadata.md +143 -0
  236. data/docs/guides/debugging/models.md +126 -0
  237. data/docs/guides/debugging/permissions.md +147 -0
  238. data/docs/guides/debugging/presenters.md +151 -0
  239. data/docs/guides/developer-tools.md +418 -0
  240. data/docs/guides/dialogs.md +392 -0
  241. data/docs/guides/display-types.md +1430 -0
  242. data/docs/guides/eager-loading.md +230 -0
  243. data/docs/guides/event-handlers.md +135 -0
  244. data/docs/guides/export.md +305 -0
  245. data/docs/guides/extensibility.md +761 -0
  246. data/docs/guides/groups.md +220 -0
  247. data/docs/guides/hierarchical-authorization.md +427 -0
  248. data/docs/guides/host-application.md +556 -0
  249. data/docs/guides/host-controller-integration.md +473 -0
  250. data/docs/guides/impersonation.md +83 -0
  251. data/docs/guides/import.md +165 -0
  252. data/docs/guides/inherited-permissions.md +459 -0
  253. data/docs/guides/menu.md +373 -0
  254. data/docs/guides/monitoring.md +254 -0
  255. data/docs/guides/oidc-setup.md +399 -0
  256. data/docs/guides/permission-source.md +205 -0
  257. data/docs/guides/permissions.md +364 -0
  258. data/docs/guides/presenters.md +2324 -0
  259. data/docs/guides/record-aliases.md +303 -0
  260. data/docs/guides/rendering-extension-points.md +280 -0
  261. data/docs/guides/role-source.md +288 -0
  262. data/docs/guides/selectbox.md +516 -0
  263. data/docs/guides/sequences.md +291 -0
  264. data/docs/guides/soft-delete.md +460 -0
  265. data/docs/guides/theming.md +129 -0
  266. data/docs/guides/tiles.md +383 -0
  267. data/docs/guides/tree-structures.md +297 -0
  268. data/docs/guides/userstamps.md +288 -0
  269. data/docs/guides/view-groups.md +259 -0
  270. data/docs/guides/view-slots.md +352 -0
  271. data/docs/guides/virtual-columns.md +810 -0
  272. data/docs/guides/workflow.md +692 -0
  273. data/docs/reference/api-backed-models.md +404 -0
  274. data/docs/reference/api-tokens.md +128 -0
  275. data/docs/reference/auditing.md +277 -0
  276. data/docs/reference/boot_lifecycle.md +188 -0
  277. data/docs/reference/cascading_selects.md +189 -0
  278. data/docs/reference/condition-operators.md +445 -0
  279. data/docs/reference/custom-fields.md +483 -0
  280. data/docs/reference/dialogs.md +286 -0
  281. data/docs/reference/doctor.md +168 -0
  282. data/docs/reference/dynamic-references.md +95 -0
  283. data/docs/reference/eager-loading.md +192 -0
  284. data/docs/reference/engine-configuration.md +989 -0
  285. data/docs/reference/export.md +309 -0
  286. data/docs/reference/forms.md +68 -0
  287. data/docs/reference/groups.md +176 -0
  288. data/docs/reference/host-controller-integration.md +342 -0
  289. data/docs/reference/i18n.md +497 -0
  290. data/docs/reference/i18n_check.md +351 -0
  291. data/docs/reference/import.md +260 -0
  292. data/docs/reference/invariant_check.md +216 -0
  293. data/docs/reference/menu.md +985 -0
  294. data/docs/reference/model-dsl.md +1157 -0
  295. data/docs/reference/models.md +2972 -0
  296. data/docs/reference/monitoring.md +222 -0
  297. data/docs/reference/oidc-bearer.md +269 -0
  298. data/docs/reference/oidc.md +407 -0
  299. data/docs/reference/page_filters.md +328 -0
  300. data/docs/reference/pages.md +1375 -0
  301. data/docs/reference/permission-source.md +185 -0
  302. data/docs/reference/permissions.md +715 -0
  303. data/docs/reference/presenter-dsl.md +1719 -0
  304. data/docs/reference/presenters.md +3627 -0
  305. data/docs/reference/role-source.md +227 -0
  306. data/docs/reference/theme-variables.md +139 -0
  307. data/docs/reference/tree-structures.md +374 -0
  308. data/docs/reference/types.md +470 -0
  309. data/docs/reference/view-groups.md +347 -0
  310. data/docs/reference/view-slots.md +228 -0
  311. data/docs/reference/virtual_forms.md +196 -0
  312. data/docs/reference/workflow-approvals.md +387 -0
  313. data/docs/reference/workflow.md +651 -0
  314. data/examples/crm/Gemfile +9 -0
  315. data/examples/crm/Gemfile.lock +417 -0
  316. data/examples/crm/Rakefile +2 -0
  317. data/examples/crm/app/actions/activity/complete.rb +20 -0
  318. data/examples/crm/app/actions/deal/close_won.rb +20 -0
  319. data/examples/crm/app/assets/config/manifest.js +3 -0
  320. data/examples/crm/app/controllers/application_controller.rb +9 -0
  321. data/examples/crm/app/event_handlers/deal/on_stage_change.rb +17 -0
  322. data/examples/crm/app/lcp_services/computed/weighted_deal_value.rb +13 -0
  323. data/examples/crm/app/lcp_services/data_providers/active_contacts_count.rb +14 -0
  324. data/examples/crm/app/lcp_services/data_providers/open_deals_count.rb +14 -0
  325. data/examples/crm/app/lcp_services/data_providers/pending_activities_count.rb +15 -0
  326. data/examples/crm/app/lcp_services/data_providers/pipeline_value.rb +27 -0
  327. data/examples/crm/app/lcp_services/data_providers/won_deals_count.rb +14 -0
  328. data/examples/crm/app/lcp_services/defaults/thirty_days_out.rb +11 -0
  329. data/examples/crm/app/lcp_services/transforms/titlecase.rb +11 -0
  330. data/examples/crm/app/lcp_services/validators/deal_credit_limit.rb +19 -0
  331. data/examples/crm/app/lcp_services/validators/deal_documents_required.rb +17 -0
  332. data/examples/crm/app/renderers/conditional_badge.rb +39 -0
  333. data/examples/crm/bin/rails +4 -0
  334. data/examples/crm/bin/rake +4 -0
  335. data/examples/crm/config/application.rb +31 -0
  336. data/examples/crm/config/boot.rb +2 -0
  337. data/examples/crm/config/database.yml +12 -0
  338. data/examples/crm/config/environment.rb +2 -0
  339. data/examples/crm/config/initializers/lcp_ruby.rb +45 -0
  340. data/examples/crm/config/lcp_ruby/menu.yml +53 -0
  341. data/examples/crm/config/lcp_ruby/models/activity.rb +43 -0
  342. data/examples/crm/config/lcp_ruby/models/city.rb +19 -0
  343. data/examples/crm/config/lcp_ruby/models/company.rb +65 -0
  344. data/examples/crm/config/lcp_ruby/models/contact.rb +62 -0
  345. data/examples/crm/config/lcp_ruby/models/country.rb +22 -0
  346. data/examples/crm/config/lcp_ruby/models/custom_field_definition.rb +60 -0
  347. data/examples/crm/config/lcp_ruby/models/deal.rb +85 -0
  348. data/examples/crm/config/lcp_ruby/models/deal_category.rb +15 -0
  349. data/examples/crm/config/lcp_ruby/models/gapfree_sequence.rb +17 -0
  350. data/examples/crm/config/lcp_ruby/models/region.rb +15 -0
  351. data/examples/crm/config/lcp_ruby/models/saved_filter.rb +50 -0
  352. data/examples/crm/config/lcp_ruby/pages/activity_quick_log.yml +19 -0
  353. data/examples/crm/config/lcp_ruby/pages/company_detail.yml +127 -0
  354. data/examples/crm/config/lcp_ruby/pages/deals_overview.yml +65 -0
  355. data/examples/crm/config/lcp_ruby/permissions/activity.yml +40 -0
  356. data/examples/crm/config/lcp_ruby/permissions/custom_field_definition.yml +16 -0
  357. data/examples/crm/config/lcp_ruby/permissions/deal.yml +54 -0
  358. data/examples/crm/config/lcp_ruby/permissions/default.yml +16 -0
  359. data/examples/crm/config/lcp_ruby/permissions/gapfree_sequence.yml +6 -0
  360. data/examples/crm/config/lcp_ruby/permissions/saved_filter.yml +27 -0
  361. data/examples/crm/config/lcp_ruby/presenters/activity.rb +140 -0
  362. data/examples/crm/config/lcp_ruby/presenters/activity_quick_form.rb +36 -0
  363. data/examples/crm/config/lcp_ruby/presenters/activity_short.rb +16 -0
  364. data/examples/crm/config/lcp_ruby/presenters/activity_tiles.rb +35 -0
  365. data/examples/crm/config/lcp_ruby/presenters/city.rb +53 -0
  366. data/examples/crm/config/lcp_ruby/presenters/company.rb +147 -0
  367. data/examples/crm/config/lcp_ruby/presenters/company_activities_zone.rb +26 -0
  368. data/examples/crm/config/lcp_ruby/presenters/company_archive.rb +37 -0
  369. data/examples/crm/config/lcp_ruby/presenters/company_contacts_zone.rb +22 -0
  370. data/examples/crm/config/lcp_ruby/presenters/company_deals_zone.rb +36 -0
  371. data/examples/crm/config/lcp_ruby/presenters/company_short.rb +21 -0
  372. data/examples/crm/config/lcp_ruby/presenters/company_show_zone.rb +38 -0
  373. data/examples/crm/config/lcp_ruby/presenters/company_sidebar.rb +15 -0
  374. data/examples/crm/config/lcp_ruby/presenters/company_tiles.rb +35 -0
  375. data/examples/crm/config/lcp_ruby/presenters/contact.rb +120 -0
  376. data/examples/crm/config/lcp_ruby/presenters/contact_quick_form.rb +17 -0
  377. data/examples/crm/config/lcp_ruby/presenters/contact_short.rb +20 -0
  378. data/examples/crm/config/lcp_ruby/presenters/contact_tiles.rb +34 -0
  379. data/examples/crm/config/lcp_ruby/presenters/country.rb +44 -0
  380. data/examples/crm/config/lcp_ruby/presenters/custom_fields.rb +124 -0
  381. data/examples/crm/config/lcp_ruby/presenters/deal.rb +181 -0
  382. data/examples/crm/config/lcp_ruby/presenters/deal_category.rb +46 -0
  383. data/examples/crm/config/lcp_ruby/presenters/deal_overview.rb +6 -0
  384. data/examples/crm/config/lcp_ruby/presenters/deal_pipeline.rb +18 -0
  385. data/examples/crm/config/lcp_ruby/presenters/deal_short.rb +25 -0
  386. data/examples/crm/config/lcp_ruby/presenters/deal_tiles.rb +48 -0
  387. data/examples/crm/config/lcp_ruby/presenters/region.rb +42 -0
  388. data/examples/crm/config/lcp_ruby/presenters/save_filter_dialog.rb +17 -0
  389. data/examples/crm/config/lcp_ruby/presenters/saved_filters.rb +93 -0
  390. data/examples/crm/config/lcp_ruby/views/activities.yml +16 -0
  391. data/examples/crm/config/lcp_ruby/views/cities.yml +10 -0
  392. data/examples/crm/config/lcp_ruby/views/companies.yml +14 -0
  393. data/examples/crm/config/lcp_ruby/views/contacts.yml +16 -0
  394. data/examples/crm/config/lcp_ruby/views/countries.yml +8 -0
  395. data/examples/crm/config/lcp_ruby/views/custom_fields.rb +9 -0
  396. data/examples/crm/config/lcp_ruby/views/deal_categories.yml +8 -0
  397. data/examples/crm/config/lcp_ruby/views/deals.yml +19 -0
  398. data/examples/crm/config/lcp_ruby/views/pipeline.yml +10 -0
  399. data/examples/crm/config/lcp_ruby/views/regions.yml +10 -0
  400. data/examples/crm/config/lcp_ruby/views/saved_filters.yml +7 -0
  401. data/examples/crm/config/locales/cs.yml +338 -0
  402. data/examples/crm/config/locales/en.yml +353 -0
  403. data/examples/crm/config/routes.rb +4 -0
  404. data/examples/crm/config/storage.yml +3 -0
  405. data/examples/crm/config.ru +2 -0
  406. data/examples/crm/db/migrate/20260219104942_create_active_storage_tables.active_storage.rb +57 -0
  407. data/examples/crm/db/schema.rb +245 -0
  408. data/examples/crm/db/seeds.rb +1111 -0
  409. data/examples/crm/erd.md +163 -0
  410. data/examples/hr/Gemfile +9 -0
  411. data/examples/hr/Gemfile.lock +419 -0
  412. data/examples/hr/Rakefile +6 -0
  413. data/examples/hr/app/actions/asset/assign_asset.rb +20 -0
  414. data/examples/hr/app/actions/asset/return_asset.rb +20 -0
  415. data/examples/hr/app/actions/candidate/advance.rb +32 -0
  416. data/examples/hr/app/actions/candidate/hire.rb +20 -0
  417. data/examples/hr/app/actions/candidate/reject_candidate.rb +20 -0
  418. data/examples/hr/app/actions/expense_claim/approve.rb +21 -0
  419. data/examples/hr/app/actions/expense_claim/reject.rb +21 -0
  420. data/examples/hr/app/actions/expense_claim/submit.rb +20 -0
  421. data/examples/hr/app/actions/interview/complete_interview.rb +20 -0
  422. data/examples/hr/app/actions/leave_request/approve.rb +21 -0
  423. data/examples/hr/app/actions/leave_request/cancel.rb +20 -0
  424. data/examples/hr/app/actions/leave_request/reject.rb +21 -0
  425. data/examples/hr/app/assets/config/manifest.js +1 -0
  426. data/examples/hr/app/assets/stylesheets/application.css +10 -0
  427. data/examples/hr/app/condition_services/is_own_org_unit.rb +14 -0
  428. data/examples/hr/app/condition_services/is_own_record.rb +20 -0
  429. data/examples/hr/app/controllers/application_controller.rb +15 -0
  430. data/examples/hr/app/event_handlers/asset_assignment/on_create.rb +24 -0
  431. data/examples/hr/app/event_handlers/candidate/on_status_change.rb +18 -0
  432. data/examples/hr/app/event_handlers/leave_request/on_status_change.rb +45 -0
  433. data/examples/hr/app/helpers/application_helper.rb +2 -0
  434. data/examples/hr/app/javascript/application.js +1 -0
  435. data/examples/hr/app/jobs/application_job.rb +7 -0
  436. data/examples/hr/app/lcp_services/computed/employee_tenure.rb +28 -0
  437. data/examples/hr/app/lcp_services/computed/leave_remaining.rb +13 -0
  438. data/examples/hr/app/lcp_services/data_providers/headcount_text.rb +14 -0
  439. data/examples/hr/app/lcp_services/data_providers/open_positions_count.rb +14 -0
  440. data/examples/hr/app/lcp_services/data_providers/pending_expenses_count.rb +14 -0
  441. data/examples/hr/app/lcp_services/data_providers/pending_leaves_count.rb +14 -0
  442. data/examples/hr/app/lcp_services/defaults/current_year.rb +11 -0
  443. data/examples/hr/app/lcp_services/transforms/titlecase.rb +11 -0
  444. data/examples/hr/app/lcp_services/validators/expense_receipt_required.rb +17 -0
  445. data/examples/hr/app/lcp_services/validators/leave_balance_check.rb +37 -0
  446. data/examples/hr/app/models/application_record.rb +3 -0
  447. data/examples/hr/app/views/layouts/application.html.erb +29 -0
  448. data/examples/hr/app/views/pwa/manifest.json.erb +22 -0
  449. data/examples/hr/app/views/pwa/service-worker.js +26 -0
  450. data/examples/hr/bin/brakeman +7 -0
  451. data/examples/hr/bin/bundler-audit +6 -0
  452. data/examples/hr/bin/ci +6 -0
  453. data/examples/hr/bin/dev +2 -0
  454. data/examples/hr/bin/docker-entrypoint +8 -0
  455. data/examples/hr/bin/importmap +4 -0
  456. data/examples/hr/bin/jobs +6 -0
  457. data/examples/hr/bin/kamal +27 -0
  458. data/examples/hr/bin/rails +4 -0
  459. data/examples/hr/bin/rake +4 -0
  460. data/examples/hr/bin/rubocop +8 -0
  461. data/examples/hr/bin/setup +35 -0
  462. data/examples/hr/bin/thrust +5 -0
  463. data/examples/hr/config/application.rb +31 -0
  464. data/examples/hr/config/boot.rb +2 -0
  465. data/examples/hr/config/bundler-audit.yml +5 -0
  466. data/examples/hr/config/cache.yml +16 -0
  467. data/examples/hr/config/ci.rb +20 -0
  468. data/examples/hr/config/credentials.yml.enc +1 -0
  469. data/examples/hr/config/database.yml +36 -0
  470. data/examples/hr/config/deploy.yml +119 -0
  471. data/examples/hr/config/environment.rb +5 -0
  472. data/examples/hr/config/environments/development.rb +66 -0
  473. data/examples/hr/config/environments/production.rb +74 -0
  474. data/examples/hr/config/environments/test.rb +45 -0
  475. data/examples/hr/config/importmap.rb +3 -0
  476. data/examples/hr/config/initializers/assets.rb +7 -0
  477. data/examples/hr/config/initializers/content_security_policy.rb +29 -0
  478. data/examples/hr/config/initializers/filter_parameter_logging.rb +8 -0
  479. data/examples/hr/config/initializers/inflections.rb +16 -0
  480. data/examples/hr/config/initializers/lcp_ruby.rb +18 -0
  481. data/examples/hr/config/lcp_ruby/menu.yml +86 -0
  482. data/examples/hr/config/lcp_ruby/models/announcement.rb +33 -0
  483. data/examples/hr/config/lcp_ruby/models/asset.rb +73 -0
  484. data/examples/hr/config/lcp_ruby/models/asset_assignment.rb +39 -0
  485. data/examples/hr/config/lcp_ruby/models/audit_log.yml +57 -0
  486. data/examples/hr/config/lcp_ruby/models/candidate.rb +68 -0
  487. data/examples/hr/config/lcp_ruby/models/custom_field_definition.rb +60 -0
  488. data/examples/hr/config/lcp_ruby/models/dashboard.rb +17 -0
  489. data/examples/hr/config/lcp_ruby/models/document.rb +38 -0
  490. data/examples/hr/config/lcp_ruby/models/employee.rb +128 -0
  491. data/examples/hr/config/lcp_ruby/models/employee_skill.rb +29 -0
  492. data/examples/hr/config/lcp_ruby/models/expense_claim.rb +70 -0
  493. data/examples/hr/config/lcp_ruby/models/goal.rb +48 -0
  494. data/examples/hr/config/lcp_ruby/models/group.rb +37 -0
  495. data/examples/hr/config/lcp_ruby/models/group_membership.rb +26 -0
  496. data/examples/hr/config/lcp_ruby/models/interview.rb +54 -0
  497. data/examples/hr/config/lcp_ruby/models/job_posting.rb +67 -0
  498. data/examples/hr/config/lcp_ruby/models/leave_balance.rb +31 -0
  499. data/examples/hr/config/lcp_ruby/models/leave_request.rb +52 -0
  500. data/examples/hr/config/lcp_ruby/models/leave_type.rb +35 -0
  501. data/examples/hr/config/lcp_ruby/models/organization_unit.rb +42 -0
  502. data/examples/hr/config/lcp_ruby/models/performance_review.rb +59 -0
  503. data/examples/hr/config/lcp_ruby/models/position.rb +43 -0
  504. data/examples/hr/config/lcp_ruby/models/skill.rb +27 -0
  505. data/examples/hr/config/lcp_ruby/models/training_course.rb +53 -0
  506. data/examples/hr/config/lcp_ruby/models/training_enrollment.rb +35 -0
  507. data/examples/hr/config/lcp_ruby/pages/dashboard.yml +101 -0
  508. data/examples/hr/config/lcp_ruby/permissions/announcement.yml +25 -0
  509. data/examples/hr/config/lcp_ruby/permissions/asset.yml +35 -0
  510. data/examples/hr/config/lcp_ruby/permissions/audit_log.yml +28 -0
  511. data/examples/hr/config/lcp_ruby/permissions/candidate.yml +25 -0
  512. data/examples/hr/config/lcp_ruby/permissions/custom_field_definition.yml +28 -0
  513. data/examples/hr/config/lcp_ruby/permissions/dashboard.yml +25 -0
  514. data/examples/hr/config/lcp_ruby/permissions/default.yml +25 -0
  515. data/examples/hr/config/lcp_ruby/permissions/document.yml +37 -0
  516. data/examples/hr/config/lcp_ruby/permissions/employee.yml +55 -0
  517. data/examples/hr/config/lcp_ruby/permissions/expense_claim.yml +45 -0
  518. data/examples/hr/config/lcp_ruby/permissions/group.yml +27 -0
  519. data/examples/hr/config/lcp_ruby/permissions/job_posting.yml +34 -0
  520. data/examples/hr/config/lcp_ruby/permissions/leave_request.yml +45 -0
  521. data/examples/hr/config/lcp_ruby/permissions/performance_review.yml +42 -0
  522. data/examples/hr/config/lcp_ruby/presenters/announcement.rb +47 -0
  523. data/examples/hr/config/lcp_ruby/presenters/asset.rb +69 -0
  524. data/examples/hr/config/lcp_ruby/presenters/asset_assignment.rb +47 -0
  525. data/examples/hr/config/lcp_ruby/presenters/audit_logs.yml +43 -0
  526. data/examples/hr/config/lcp_ruby/presenters/candidate.rb +71 -0
  527. data/examples/hr/config/lcp_ruby/presenters/custom_fields.rb +124 -0
  528. data/examples/hr/config/lcp_ruby/presenters/dashboard.rb +37 -0
  529. data/examples/hr/config/lcp_ruby/presenters/document.rb +46 -0
  530. data/examples/hr/config/lcp_ruby/presenters/employee.rb +167 -0
  531. data/examples/hr/config/lcp_ruby/presenters/employee_archive.rb +38 -0
  532. data/examples/hr/config/lcp_ruby/presenters/employee_directory.rb +27 -0
  533. data/examples/hr/config/lcp_ruby/presenters/employee_skill.rb +57 -0
  534. data/examples/hr/config/lcp_ruby/presenters/expense_claim.rb +76 -0
  535. data/examples/hr/config/lcp_ruby/presenters/goal.rb +60 -0
  536. data/examples/hr/config/lcp_ruby/presenters/group.rb +48 -0
  537. data/examples/hr/config/lcp_ruby/presenters/interview.rb +59 -0
  538. data/examples/hr/config/lcp_ruby/presenters/job_posting.rb +73 -0
  539. data/examples/hr/config/lcp_ruby/presenters/leave_balance.rb +50 -0
  540. data/examples/hr/config/lcp_ruby/presenters/leave_request.rb +89 -0
  541. data/examples/hr/config/lcp_ruby/presenters/leave_type.rb +52 -0
  542. data/examples/hr/config/lcp_ruby/presenters/organization_unit.rb +56 -0
  543. data/examples/hr/config/lcp_ruby/presenters/performance_review.rb +87 -0
  544. data/examples/hr/config/lcp_ruby/presenters/position.rb +54 -0
  545. data/examples/hr/config/lcp_ruby/presenters/skill.rb +45 -0
  546. data/examples/hr/config/lcp_ruby/presenters/training_course.rb +61 -0
  547. data/examples/hr/config/lcp_ruby/presenters/training_enrollment.rb +49 -0
  548. data/examples/hr/config/lcp_ruby/views/announcements.yml +8 -0
  549. data/examples/hr/config/lcp_ruby/views/asset_assignments.yml +10 -0
  550. data/examples/hr/config/lcp_ruby/views/assets.yml +8 -0
  551. data/examples/hr/config/lcp_ruby/views/audit_logs.yml +8 -0
  552. data/examples/hr/config/lcp_ruby/views/candidates.yml +8 -0
  553. data/examples/hr/config/lcp_ruby/views/custom_fields.yml +8 -0
  554. data/examples/hr/config/lcp_ruby/views/dashboard.yml +6 -0
  555. data/examples/hr/config/lcp_ruby/views/documents.yml +10 -0
  556. data/examples/hr/config/lcp_ruby/views/employee_skills.yml +10 -0
  557. data/examples/hr/config/lcp_ruby/views/employees.yml +14 -0
  558. data/examples/hr/config/lcp_ruby/views/expense_claims.yml +10 -0
  559. data/examples/hr/config/lcp_ruby/views/goals.yml +10 -0
  560. data/examples/hr/config/lcp_ruby/views/groups.yml +8 -0
  561. data/examples/hr/config/lcp_ruby/views/interviews.yml +8 -0
  562. data/examples/hr/config/lcp_ruby/views/job_postings.yml +6 -0
  563. data/examples/hr/config/lcp_ruby/views/leave_balances.yml +10 -0
  564. data/examples/hr/config/lcp_ruby/views/leave_requests.yml +10 -0
  565. data/examples/hr/config/lcp_ruby/views/leave_types.yml +8 -0
  566. data/examples/hr/config/lcp_ruby/views/organization_units.yml +8 -0
  567. data/examples/hr/config/lcp_ruby/views/performance_reviews.yml +10 -0
  568. data/examples/hr/config/lcp_ruby/views/positions.yml +8 -0
  569. data/examples/hr/config/lcp_ruby/views/skills.yml +8 -0
  570. data/examples/hr/config/lcp_ruby/views/training_courses.yml +8 -0
  571. data/examples/hr/config/lcp_ruby/views/training_enrollments.yml +10 -0
  572. data/examples/hr/config/locales/cs.yml +496 -0
  573. data/examples/hr/config/locales/en.yml +740 -0
  574. data/examples/hr/config/locales/sk.yml +496 -0
  575. data/examples/hr/config/puma.rb +42 -0
  576. data/examples/hr/config/queue.yml +18 -0
  577. data/examples/hr/config/recurring.yml +15 -0
  578. data/examples/hr/config/routes.rb +4 -0
  579. data/examples/hr/config/storage.yml +27 -0
  580. data/examples/hr/config.ru +6 -0
  581. data/examples/hr/db/cache_schema.rb +12 -0
  582. data/examples/hr/db/migrate/20260303202825_create_active_storage_tables.active_storage.rb +57 -0
  583. data/examples/hr/db/queue_schema.rb +129 -0
  584. data/examples/hr/db/schema.rb +588 -0
  585. data/examples/hr/db/seeds.rb +932 -0
  586. data/examples/hr/erd.md +396 -0
  587. data/examples/hr/public/400.html +135 -0
  588. data/examples/hr/public/404.html +135 -0
  589. data/examples/hr/public/406-unsupported-browser.html +135 -0
  590. data/examples/hr/public/422.html +135 -0
  591. data/examples/hr/public/500.html +135 -0
  592. data/examples/hr/public/icon.svg +3 -0
  593. data/examples/hr/public/robots.txt +1 -0
  594. data/examples/showcase/Gemfile +15 -0
  595. data/examples/showcase/Gemfile.lock +425 -0
  596. data/examples/showcase/Rakefile +2 -0
  597. data/examples/showcase/app/actions/showcase_batch_task/assign_batch.rb +20 -0
  598. data/examples/showcase/app/actions/showcase_batch_task/close_task.rb +21 -0
  599. data/examples/showcase/app/actions/showcase_condition/approve.rb +20 -0
  600. data/examples/showcase/app/actions/showcase_permission/lock.rb +20 -0
  601. data/examples/showcase/app/assets/config/manifest.js +3 -0
  602. data/examples/showcase/app/assets/stylesheets/application.css +27 -0
  603. data/examples/showcase/app/condition_services/budget_threshold.rb +16 -0
  604. data/examples/showcase/app/condition_services/overdue_check.rb +11 -0
  605. data/examples/showcase/app/controllers/application_controller.rb +2 -0
  606. data/examples/showcase/app/controllers/docs_controller.rb +48 -0
  607. data/examples/showcase/app/controllers/host_inventory_items_managed_controller.rb +90 -0
  608. data/examples/showcase/app/controllers/host_inventory_items_report_controller.rb +39 -0
  609. data/examples/showcase/app/controllers/host_inventory_items_wizard_controller.rb +50 -0
  610. data/examples/showcase/app/data_providers/showcase_amount_provider.rb +52 -0
  611. data/examples/showcase/app/data_providers/weather_station_provider.rb +140 -0
  612. data/examples/showcase/app/event_handlers/showcase_model/on_status_change.rb +17 -0
  613. data/examples/showcase/app/event_handlers/showcase_permission/on_status_change.rb +17 -0
  614. data/examples/showcase/app/event_handlers/showcase_workflow/log_review_exit.rb +16 -0
  615. data/examples/showcase/app/event_handlers/showcase_workflow/notify_reviewers.rb +15 -0
  616. data/examples/showcase/app/event_handlers/showcase_workflow/request_submitted.rb +15 -0
  617. data/examples/showcase/app/lcp_metrics/showcase_metrics.rb +31 -0
  618. data/examples/showcase/app/lcp_services/computed/showcase_score.rb +18 -0
  619. data/examples/showcase/app/lcp_services/computed/showcase_total.rb +13 -0
  620. data/examples/showcase/app/lcp_services/defaults/one_week_from_now.rb +11 -0
  621. data/examples/showcase/app/lcp_services/menu_items/recent_announcements.rb +36 -0
  622. data/examples/showcase/app/lcp_services/virtual_columns/project_health.rb +26 -0
  623. data/examples/showcase/app/model_extensions/lcp_error_log_extension.rb +12 -0
  624. data/examples/showcase/app/models/host_inventory_item.rb +20 -0
  625. data/examples/showcase/app/models/platform_profile.rb +27 -0
  626. data/examples/showcase/app/models/platform_user.rb +5 -0
  627. data/examples/showcase/app/views/docs/show.html.erb +19 -0
  628. data/examples/showcase/app/views/host_inventory_items_report/index.html.erb +61 -0
  629. data/examples/showcase/app/views/host_inventory_items_report/show.html.erb +39 -0
  630. data/examples/showcase/app/views/layouts/docs.html.erb +46 -0
  631. data/examples/showcase/app/views/showcase/menu_renderers/_status_pill.html.erb +17 -0
  632. data/examples/showcase/app/views/showcase_custom/_activity_timeline.html.erb +37 -0
  633. data/examples/showcase/app/views/showcase_custom/_card_index.html.erb +74 -0
  634. data/examples/showcase/app/views/showcase_custom/_detail_show.html.erb +115 -0
  635. data/examples/showcase/app/views/showcase_custom/_location_map.html.erb +29 -0
  636. data/examples/showcase/app/views/showcase_custom/_location_view.html.erb +34 -0
  637. data/examples/showcase/app/views/showcase_custom/_quick_stats.html.erb +50 -0
  638. data/examples/showcase/app/views/showcase_custom/_stats_sidebar.html.erb +42 -0
  639. data/examples/showcase/app/views/showcase_custom/_tags_editor.html.erb +48 -0
  640. data/examples/showcase/bin/rails +4 -0
  641. data/examples/showcase/bin/rake +4 -0
  642. data/examples/showcase/config/application.rb +37 -0
  643. data/examples/showcase/config/boot.rb +2 -0
  644. data/examples/showcase/config/database.yml +12 -0
  645. data/examples/showcase/config/environment.rb +2 -0
  646. data/examples/showcase/config/initializers/devise.rb +5 -0
  647. data/examples/showcase/config/initializers/lcp_ruby.rb +175 -0
  648. data/examples/showcase/config/lcp_ruby/auth.yml +60 -0
  649. data/examples/showcase/config/lcp_ruby/jobs/data_import.yml +7 -0
  650. data/examples/showcase/config/lcp_ruby/jobs/showcase_cleanup.yml +11 -0
  651. data/examples/showcase/config/lcp_ruby/jobs/showcase_event_triggered.yml +11 -0
  652. data/examples/showcase/config/lcp_ruby/jobs/showcase_multi_step.yml +9 -0
  653. data/examples/showcase/config/lcp_ruby/jobs/showcase_webhook.yml +13 -0
  654. data/examples/showcase/config/lcp_ruby/menu.yml +249 -0
  655. data/examples/showcase/config/lcp_ruby/models/_base_document.rb +26 -0
  656. data/examples/showcase/config/lcp_ruby/models/_categorized_document.rb +19 -0
  657. data/examples/showcase/config/lcp_ruby/models/_contactable.rb +20 -0
  658. data/examples/showcase/config/lcp_ruby/models/api_token.rb +23 -0
  659. data/examples/showcase/config/lcp_ruby/models/article.rb +49 -0
  660. data/examples/showcase/config/lcp_ruby/models/article_tag.rb +10 -0
  661. data/examples/showcase/config/lcp_ruby/models/author.rb +16 -0
  662. data/examples/showcase/config/lcp_ruby/models/batch_operation.yml +79 -0
  663. data/examples/showcase/config/lcp_ruby/models/batch_operation_item.yml +45 -0
  664. data/examples/showcase/config/lcp_ruby/models/category.rb +23 -0
  665. data/examples/showcase/config/lcp_ruby/models/comment.rb +21 -0
  666. data/examples/showcase/config/lcp_ruby/models/custom_field_definition.rb +59 -0
  667. data/examples/showcase/config/lcp_ruby/models/department.rb +32 -0
  668. data/examples/showcase/config/lcp_ruby/models/employee.rb +52 -0
  669. data/examples/showcase/config/lcp_ruby/models/employee_emergency_contact.rb +24 -0
  670. data/examples/showcase/config/lcp_ruby/models/employee_profile.rb +18 -0
  671. data/examples/showcase/config/lcp_ruby/models/employee_skill.rb +10 -0
  672. data/examples/showcase/config/lcp_ruby/models/export_log.yml +27 -0
  673. data/examples/showcase/config/lcp_ruby/models/export_profile.yml +37 -0
  674. data/examples/showcase/config/lcp_ruby/models/feature.rb +76 -0
  675. data/examples/showcase/config/lcp_ruby/models/gapfree_sequence.rb +17 -0
  676. data/examples/showcase/config/lcp_ruby/models/group.rb +26 -0
  677. data/examples/showcase/config/lcp_ruby/models/group_membership.rb +21 -0
  678. data/examples/showcase/config/lcp_ruby/models/group_role_mapping.rb +14 -0
  679. data/examples/showcase/config/lcp_ruby/models/host_inventory_item.yml +111 -0
  680. data/examples/showcase/config/lcp_ruby/models/import_profile.rb +30 -0
  681. data/examples/showcase/config/lcp_ruby/models/import_row.rb +32 -0
  682. data/examples/showcase/config/lcp_ruby/models/ingredient_def.rb +11 -0
  683. data/examples/showcase/config/lcp_ruby/models/lcp_error_log.yml +61 -0
  684. data/examples/showcase/config/lcp_ruby/models/page_config.rb +19 -0
  685. data/examples/showcase/config/lcp_ruby/models/permission_config.rb +21 -0
  686. data/examples/showcase/config/lcp_ruby/models/pipeline.rb +15 -0
  687. data/examples/showcase/config/lcp_ruby/models/pipeline_stage.rb +17 -0
  688. data/examples/showcase/config/lcp_ruby/models/platform_profile.rb +104 -0
  689. data/examples/showcase/config/lcp_ruby/models/profile_setting.rb +17 -0
  690. data/examples/showcase/config/lcp_ruby/models/profile_tag.rb +19 -0
  691. data/examples/showcase/config/lcp_ruby/models/project.rb +23 -0
  692. data/examples/showcase/config/lcp_ruby/models/role.rb +24 -0
  693. data/examples/showcase/config/lcp_ruby/models/saved_filter.rb +50 -0
  694. data/examples/showcase/config/lcp_ruby/models/showcase_aggregate.rb +93 -0
  695. data/examples/showcase/config/lcp_ruby/models/showcase_aggregate_company.rb +14 -0
  696. data/examples/showcase/config/lcp_ruby/models/showcase_aggregate_item.rb +25 -0
  697. data/examples/showcase/config/lcp_ruby/models/showcase_announcement.rb +20 -0
  698. data/examples/showcase/config/lcp_ruby/models/showcase_array.rb +45 -0
  699. data/examples/showcase/config/lcp_ruby/models/showcase_attachment.rb +49 -0
  700. data/examples/showcase/config/lcp_ruby/models/showcase_audit_log.yml +44 -0
  701. data/examples/showcase/config/lcp_ruby/models/showcase_audited_record.rb +20 -0
  702. data/examples/showcase/config/lcp_ruby/models/showcase_batch_task.rb +27 -0
  703. data/examples/showcase/config/lcp_ruby/models/showcase_business_unit.rb +26 -0
  704. data/examples/showcase/config/lcp_ruby/models/showcase_condition.rb +24 -0
  705. data/examples/showcase/config/lcp_ruby/models/showcase_condition_category.rb +16 -0
  706. data/examples/showcase/config/lcp_ruby/models/showcase_condition_task.rb +16 -0
  707. data/examples/showcase/config/lcp_ruby/models/showcase_condition_threshold.rb +13 -0
  708. data/examples/showcase/config/lcp_ruby/models/showcase_contact.rb +22 -0
  709. data/examples/showcase/config/lcp_ruby/models/showcase_custom_render.rb +38 -0
  710. data/examples/showcase/config/lcp_ruby/models/showcase_delete_reason.rb +11 -0
  711. data/examples/showcase/config/lcp_ruby/models/showcase_division.rb +31 -0
  712. data/examples/showcase/config/lcp_ruby/models/showcase_extensibility.rb +25 -0
  713. data/examples/showcase/config/lcp_ruby/models/showcase_field.rb +53 -0
  714. data/examples/showcase/config/lcp_ruby/models/showcase_form.rb +23 -0
  715. data/examples/showcase/config/lcp_ruby/models/showcase_form_action.rb +38 -0
  716. data/examples/showcase/config/lcp_ruby/models/showcase_grade.rb +18 -0
  717. data/examples/showcase/config/lcp_ruby/models/showcase_hr_employee.rb +90 -0
  718. data/examples/showcase/config/lcp_ruby/models/showcase_item_class.rb +31 -0
  719. data/examples/showcase/config/lcp_ruby/models/showcase_job_execution.rb +49 -0
  720. data/examples/showcase/config/lcp_ruby/models/showcase_memo.rb +23 -0
  721. data/examples/showcase/config/lcp_ruby/models/showcase_model.rb +74 -0
  722. data/examples/showcase/config/lcp_ruby/models/showcase_organization.rb +31 -0
  723. data/examples/showcase/config/lcp_ruby/models/showcase_permission.rb +30 -0
  724. data/examples/showcase/config/lcp_ruby/models/showcase_person.rb +23 -0
  725. data/examples/showcase/config/lcp_ruby/models/showcase_positioning.rb +19 -0
  726. data/examples/showcase/config/lcp_ruby/models/showcase_quick_note.rb +13 -0
  727. data/examples/showcase/config/lcp_ruby/models/showcase_recipe.rb +17 -0
  728. data/examples/showcase/config/lcp_ruby/models/showcase_report.rb +32 -0
  729. data/examples/showcase/config/lcp_ruby/models/showcase_school_class.rb +17 -0
  730. data/examples/showcase/config/lcp_ruby/models/showcase_search.rb +84 -0
  731. data/examples/showcase/config/lcp_ruby/models/showcase_sequence.rb +46 -0
  732. data/examples/showcase/config/lcp_ruby/models/showcase_soft_delete.rb +30 -0
  733. data/examples/showcase/config/lcp_ruby/models/showcase_soft_delete_item.rb +21 -0
  734. data/examples/showcase/config/lcp_ruby/models/showcase_student.rb +17 -0
  735. data/examples/showcase/config/lcp_ruby/models/showcase_type_default.rb +49 -0
  736. data/examples/showcase/config/lcp_ruby/models/showcase_userstamps.rb +26 -0
  737. data/examples/showcase/config/lcp_ruby/models/showcase_virtual_field.rb +68 -0
  738. data/examples/showcase/config/lcp_ruby/models/showcase_workflow.rb +54 -0
  739. data/examples/showcase/config/lcp_ruby/models/skill.rb +22 -0
  740. data/examples/showcase/config/lcp_ruby/models/tag.rb +16 -0
  741. data/examples/showcase/config/lcp_ruby/models/user.rb +54 -0
  742. data/examples/showcase/config/lcp_ruby/models/weather_station.rb +20 -0
  743. data/examples/showcase/config/lcp_ruby/models/workflow_approval_request.yml +77 -0
  744. data/examples/showcase/config/lcp_ruby/models/workflow_approval_step.yml +56 -0
  745. data/examples/showcase/config/lcp_ruby/models/workflow_approval_task.yml +51 -0
  746. data/examples/showcase/config/lcp_ruby/models/workflow_audit_log.yml +74 -0
  747. data/examples/showcase/config/lcp_ruby/pages/article_detail.yml +32 -0
  748. data/examples/showcase/config/lcp_ruby/pages/author_detail.yml +27 -0
  749. data/examples/showcase/config/lcp_ruby/pages/category_detail.yml +24 -0
  750. data/examples/showcase/config/lcp_ruby/pages/chart_showcase.yml +151 -0
  751. data/examples/showcase/config/lcp_ruby/pages/department_detail.yml +55 -0
  752. data/examples/showcase/config/lcp_ruby/pages/department_explorer.yml +60 -0
  753. data/examples/showcase/config/lcp_ruby/pages/employee_overview.yml +106 -0
  754. data/examples/showcase/config/lcp_ruby/pages/employee_transfer_dialog.yml +24 -0
  755. data/examples/showcase/config/lcp_ruby/pages/hr_turnover_dashboard.yml +288 -0
  756. data/examples/showcase/config/lcp_ruby/pages/main_dashboard.yml +142 -0
  757. data/examples/showcase/config/lcp_ruby/pages/monitoring_dashboard.yml +58 -0
  758. data/examples/showcase/config/lcp_ruby/pages/pipeline_detail.yml +16 -0
  759. data/examples/showcase/config/lcp_ruby/pages/showcase_custom_zones.yml +39 -0
  760. data/examples/showcase/config/lcp_ruby/pages/showcase_form_action_dialog.yml +11 -0
  761. data/examples/showcase/config/lcp_ruby/pages/workflow_request_detail.yml +34 -0
  762. data/examples/showcase/config/lcp_ruby/permissions/api_token.yml +26 -0
  763. data/examples/showcase/config/lcp_ruby/permissions/batch_operation.yml +36 -0
  764. data/examples/showcase/config/lcp_ruby/permissions/custom_field_definition.yml +15 -0
  765. data/examples/showcase/config/lcp_ruby/permissions/default.yml +28 -0
  766. data/examples/showcase/config/lcp_ruby/permissions/export_log.yml +23 -0
  767. data/examples/showcase/config/lcp_ruby/permissions/export_profile.yml +25 -0
  768. data/examples/showcase/config/lcp_ruby/permissions/gapfree_sequence.yml +6 -0
  769. data/examples/showcase/config/lcp_ruby/permissions/group.yml +20 -0
  770. data/examples/showcase/config/lcp_ruby/permissions/group_membership.yml +20 -0
  771. data/examples/showcase/config/lcp_ruby/permissions/group_role_mapping.yml +20 -0
  772. data/examples/showcase/config/lcp_ruby/permissions/host_inventory_item.yml +34 -0
  773. data/examples/showcase/config/lcp_ruby/permissions/import_profile.yml +29 -0
  774. data/examples/showcase/config/lcp_ruby/permissions/import_row.yml +17 -0
  775. data/examples/showcase/config/lcp_ruby/permissions/lcp_error_log.yml +8 -0
  776. data/examples/showcase/config/lcp_ruby/permissions/page_config.yml +15 -0
  777. data/examples/showcase/config/lcp_ruby/permissions/permission_config.yml +15 -0
  778. data/examples/showcase/config/lcp_ruby/permissions/platform_profile.yml +23 -0
  779. data/examples/showcase/config/lcp_ruby/permissions/profile_setting.yml +23 -0
  780. data/examples/showcase/config/lcp_ruby/permissions/profile_tag.yml +23 -0
  781. data/examples/showcase/config/lcp_ruby/permissions/role.yml +20 -0
  782. data/examples/showcase/config/lcp_ruby/permissions/saved_filter.yml +39 -0
  783. data/examples/showcase/config/lcp_ruby/permissions/showcase_announcement.yml +22 -0
  784. data/examples/showcase/config/lcp_ruby/permissions/showcase_audit_log.yml +15 -0
  785. data/examples/showcase/config/lcp_ruby/permissions/showcase_audited_record.yml +15 -0
  786. data/examples/showcase/config/lcp_ruby/permissions/showcase_batch_task.yml +31 -0
  787. data/examples/showcase/config/lcp_ruby/permissions/showcase_condition.yml +54 -0
  788. data/examples/showcase/config/lcp_ruby/permissions/showcase_contact.yml +21 -0
  789. data/examples/showcase/config/lcp_ruby/permissions/showcase_custom_render.yml +21 -0
  790. data/examples/showcase/config/lcp_ruby/permissions/showcase_delete_reason.yml +12 -0
  791. data/examples/showcase/config/lcp_ruby/permissions/showcase_form_action.yml +26 -0
  792. data/examples/showcase/config/lcp_ruby/permissions/showcase_grade.yml +33 -0
  793. data/examples/showcase/config/lcp_ruby/permissions/showcase_job_execution.yml +23 -0
  794. data/examples/showcase/config/lcp_ruby/permissions/showcase_permission.yml +47 -0
  795. data/examples/showcase/config/lcp_ruby/permissions/showcase_quick_note.yml +12 -0
  796. data/examples/showcase/config/lcp_ruby/permissions/showcase_school_class.yml +37 -0
  797. data/examples/showcase/config/lcp_ruby/permissions/showcase_student.yml +43 -0
  798. data/examples/showcase/config/lcp_ruby/permissions/showcase_workflow.yml +34 -0
  799. data/examples/showcase/config/lcp_ruby/permissions/workflow_approval_request.yml +18 -0
  800. data/examples/showcase/config/lcp_ruby/permissions/workflow_approval_step.yml +18 -0
  801. data/examples/showcase/config/lcp_ruby/permissions/workflow_approval_task.yml +18 -0
  802. data/examples/showcase/config/lcp_ruby/permissions/workflow_audit_log.yml +19 -0
  803. data/examples/showcase/config/lcp_ruby/presenters/announcements.rb +59 -0
  804. data/examples/showcase/config/lcp_ruby/presenters/approval_requests.rb +69 -0
  805. data/examples/showcase/config/lcp_ruby/presenters/approval_steps.rb +59 -0
  806. data/examples/showcase/config/lcp_ruby/presenters/approval_tasks.rb +65 -0
  807. data/examples/showcase/config/lcp_ruby/presenters/article_comments_zone.rb +12 -0
  808. data/examples/showcase/config/lcp_ruby/presenters/article_related_zone.rb +15 -0
  809. data/examples/showcase/config/lcp_ruby/presenters/articles.rb +149 -0
  810. data/examples/showcase/config/lcp_ruby/presenters/articles_tiles.rb +30 -0
  811. data/examples/showcase/config/lcp_ruby/presenters/author_articles_zone.rb +12 -0
  812. data/examples/showcase/config/lcp_ruby/presenters/author_show_zone.rb +12 -0
  813. data/examples/showcase/config/lcp_ruby/presenters/authors.rb +39 -0
  814. data/examples/showcase/config/lcp_ruby/presenters/batch_operation_items.yml +45 -0
  815. data/examples/showcase/config/lcp_ruby/presenters/batch_operations.yml +66 -0
  816. data/examples/showcase/config/lcp_ruby/presenters/categories.rb +50 -0
  817. data/examples/showcase/config/lcp_ruby/presenters/category_articles_zone.rb +20 -0
  818. data/examples/showcase/config/lcp_ruby/presenters/category_children_zone.rb +10 -0
  819. data/examples/showcase/config/lcp_ruby/presenters/comment_quick_add_dialog.rb +15 -0
  820. data/examples/showcase/config/lcp_ruby/presenters/custom_fields.rb +124 -0
  821. data/examples/showcase/config/lcp_ruby/presenters/dashboard_employees.rb +16 -0
  822. data/examples/showcase/config/lcp_ruby/presenters/delete_reason_dialog.rb +13 -0
  823. data/examples/showcase/config/lcp_ruby/presenters/departments.rb +55 -0
  824. data/examples/showcase/config/lcp_ruby/presenters/dept_add_employee_dialog.rb +19 -0
  825. data/examples/showcase/config/lcp_ruby/presenters/dept_children_zone.rb +10 -0
  826. data/examples/showcase/config/lcp_ruby/presenters/dept_detail_zone.rb +14 -0
  827. data/examples/showcase/config/lcp_ruby/presenters/dept_employees_zone.rb +16 -0
  828. data/examples/showcase/config/lcp_ruby/presenters/dept_list_selection_zone.rb +19 -0
  829. data/examples/showcase/config/lcp_ruby/presenters/employee_overview_index_zone.rb +36 -0
  830. data/examples/showcase/config/lcp_ruby/presenters/employee_quick_add_dialog.rb +14 -0
  831. data/examples/showcase/config/lcp_ruby/presenters/employee_show_zone.rb +20 -0
  832. data/examples/showcase/config/lcp_ruby/presenters/employee_transfer_form_zone.rb +19 -0
  833. data/examples/showcase/config/lcp_ruby/presenters/employees.rb +165 -0
  834. data/examples/showcase/config/lcp_ruby/presenters/employees_tiles.rb +33 -0
  835. data/examples/showcase/config/lcp_ruby/presenters/export_logs.yml +58 -0
  836. data/examples/showcase/config/lcp_ruby/presenters/export_profiles.yml +70 -0
  837. data/examples/showcase/config/lcp_ruby/presenters/extensibility_quick_edit_dialog.rb +13 -0
  838. data/examples/showcase/config/lcp_ruby/presenters/feature_kanban.rb +30 -0
  839. data/examples/showcase/config/lcp_ruby/presenters/features_card.rb +179 -0
  840. data/examples/showcase/config/lcp_ruby/presenters/features_hub.rb +44 -0
  841. data/examples/showcase/config/lcp_ruby/presenters/features_table.rb +37 -0
  842. data/examples/showcase/config/lcp_ruby/presenters/features_tiles.rb +48 -0
  843. data/examples/showcase/config/lcp_ruby/presenters/group_memberships.rb +54 -0
  844. data/examples/showcase/config/lcp_ruby/presenters/group_role_mappings.rb +48 -0
  845. data/examples/showcase/config/lcp_ruby/presenters/groups.rb +74 -0
  846. data/examples/showcase/config/lcp_ruby/presenters/host_inventory_items.rb +99 -0
  847. data/examples/showcase/config/lcp_ruby/presenters/host_inventory_items_managed.rb +84 -0
  848. data/examples/showcase/config/lcp_ruby/presenters/host_inventory_items_report.rb +40 -0
  849. data/examples/showcase/config/lcp_ruby/presenters/host_inventory_items_wizard.rb +76 -0
  850. data/examples/showcase/config/lcp_ruby/presenters/import_profiles.rb +61 -0
  851. data/examples/showcase/config/lcp_ruby/presenters/import_rows.rb +39 -0
  852. data/examples/showcase/config/lcp_ruby/presenters/lcp_error_logs.yml +46 -0
  853. data/examples/showcase/config/lcp_ruby/presenters/my_api_tokens.rb +35 -0
  854. data/examples/showcase/config/lcp_ruby/presenters/my_api_tokens_create_dialog.rb +27 -0
  855. data/examples/showcase/config/lcp_ruby/presenters/my_employee_profile.rb +24 -0
  856. data/examples/showcase/config/lcp_ruby/presenters/my_settings.rb +50 -0
  857. data/examples/showcase/config/lcp_ruby/presenters/page_configs.rb +56 -0
  858. data/examples/showcase/config/lcp_ruby/presenters/permission_configs.rb +58 -0
  859. data/examples/showcase/config/lcp_ruby/presenters/pipeline_edit_zone.rb +11 -0
  860. data/examples/showcase/config/lcp_ruby/presenters/pipeline_stages.rb +51 -0
  861. data/examples/showcase/config/lcp_ruby/presenters/pipeline_stages_zone.rb +11 -0
  862. data/examples/showcase/config/lcp_ruby/presenters/pipelines.rb +40 -0
  863. data/examples/showcase/config/lcp_ruby/presenters/platform_profiles.rb +90 -0
  864. data/examples/showcase/config/lcp_ruby/presenters/projects.rb +58 -0
  865. data/examples/showcase/config/lcp_ruby/presenters/quick_note_dialog.rb +14 -0
  866. data/examples/showcase/config/lcp_ruby/presenters/roles.rb +60 -0
  867. data/examples/showcase/config/lcp_ruby/presenters/save_filter_dialog.rb +17 -0
  868. data/examples/showcase/config/lcp_ruby/presenters/saved_filters.rb +94 -0
  869. data/examples/showcase/config/lcp_ruby/presenters/showcase_aggregate_items.rb +61 -0
  870. data/examples/showcase/config/lcp_ruby/presenters/showcase_aggregates.rb +115 -0
  871. data/examples/showcase/config/lcp_ruby/presenters/showcase_aggregates_tiles.rb +44 -0
  872. data/examples/showcase/config/lcp_ruby/presenters/showcase_amount_kanban.rb +31 -0
  873. data/examples/showcase/config/lcp_ruby/presenters/showcase_arrays.rb +140 -0
  874. data/examples/showcase/config/lcp_ruby/presenters/showcase_attachments.rb +66 -0
  875. data/examples/showcase/config/lcp_ruby/presenters/showcase_audit_logs.rb +46 -0
  876. data/examples/showcase/config/lcp_ruby/presenters/showcase_audited_records.rb +58 -0
  877. data/examples/showcase/config/lcp_ruby/presenters/showcase_batch_tasks.rb +97 -0
  878. data/examples/showcase/config/lcp_ruby/presenters/showcase_batch_tasks_archive.rb +52 -0
  879. data/examples/showcase/config/lcp_ruby/presenters/showcase_business_units.rb +43 -0
  880. data/examples/showcase/config/lcp_ruby/presenters/showcase_conditions.rb +195 -0
  881. data/examples/showcase/config/lcp_ruby/presenters/showcase_contacts.rb +82 -0
  882. data/examples/showcase/config/lcp_ruby/presenters/showcase_custom_render_with.rb +50 -0
  883. data/examples/showcase/config/lcp_ruby/presenters/showcase_custom_sections.rb +88 -0
  884. data/examples/showcase/config/lcp_ruby/presenters/showcase_custom_zones_main.rb +75 -0
  885. data/examples/showcase/config/lcp_ruby/presenters/showcase_divisions.rb +53 -0
  886. data/examples/showcase/config/lcp_ruby/presenters/showcase_extensibility.rb +48 -0
  887. data/examples/showcase/config/lcp_ruby/presenters/showcase_fields_card.rb +34 -0
  888. data/examples/showcase/config/lcp_ruby/presenters/showcase_fields_table.rb +128 -0
  889. data/examples/showcase/config/lcp_ruby/presenters/showcase_fields_tiles.rb +42 -0
  890. data/examples/showcase/config/lcp_ruby/presenters/showcase_form_action_dialog.rb +27 -0
  891. data/examples/showcase/config/lcp_ruby/presenters/showcase_form_actions.rb +132 -0
  892. data/examples/showcase/config/lcp_ruby/presenters/showcase_form_actions_overflow.rb +76 -0
  893. data/examples/showcase/config/lcp_ruby/presenters/showcase_forms.rb +110 -0
  894. data/examples/showcase/config/lcp_ruby/presenters/showcase_grades.rb +38 -0
  895. data/examples/showcase/config/lcp_ruby/presenters/showcase_hr_employees.rb +84 -0
  896. data/examples/showcase/config/lcp_ruby/presenters/showcase_item_classes.rb +120 -0
  897. data/examples/showcase/config/lcp_ruby/presenters/showcase_job_executions.rb +150 -0
  898. data/examples/showcase/config/lcp_ruby/presenters/showcase_memos.rb +96 -0
  899. data/examples/showcase/config/lcp_ruby/presenters/showcase_models.rb +112 -0
  900. data/examples/showcase/config/lcp_ruby/presenters/showcase_organizations.rb +106 -0
  901. data/examples/showcase/config/lcp_ruby/presenters/showcase_people.rb +97 -0
  902. data/examples/showcase/config/lcp_ruby/presenters/showcase_permissions.rb +84 -0
  903. data/examples/showcase/config/lcp_ruby/presenters/showcase_positioning.rb +61 -0
  904. data/examples/showcase/config/lcp_ruby/presenters/showcase_recipes.rb +105 -0
  905. data/examples/showcase/config/lcp_ruby/presenters/showcase_recipes_raw.rb +32 -0
  906. data/examples/showcase/config/lcp_ruby/presenters/showcase_reports.rb +109 -0
  907. data/examples/showcase/config/lcp_ruby/presenters/showcase_school_classes.rb +34 -0
  908. data/examples/showcase/config/lcp_ruby/presenters/showcase_searches.rb +226 -0
  909. data/examples/showcase/config/lcp_ruby/presenters/showcase_sequences.rb +67 -0
  910. data/examples/showcase/config/lcp_ruby/presenters/showcase_soft_delete.rb +88 -0
  911. data/examples/showcase/config/lcp_ruby/presenters/showcase_soft_delete_archive.rb +52 -0
  912. data/examples/showcase/config/lcp_ruby/presenters/showcase_soft_delete_items.rb +47 -0
  913. data/examples/showcase/config/lcp_ruby/presenters/showcase_students.rb +33 -0
  914. data/examples/showcase/config/lcp_ruby/presenters/showcase_type_defaults.rb +92 -0
  915. data/examples/showcase/config/lcp_ruby/presenters/showcase_userstamps.rb +76 -0
  916. data/examples/showcase/config/lcp_ruby/presenters/showcase_virtual_fields.rb +104 -0
  917. data/examples/showcase/config/lcp_ruby/presenters/showcase_workflow_admin.rb +24 -0
  918. data/examples/showcase/config/lcp_ruby/presenters/showcase_workflow_kanban.rb +36 -0
  919. data/examples/showcase/config/lcp_ruby/presenters/showcase_workflows.rb +103 -0
  920. data/examples/showcase/config/lcp_ruby/presenters/tags.rb +35 -0
  921. data/examples/showcase/config/lcp_ruby/presenters/users.rb +61 -0
  922. data/examples/showcase/config/lcp_ruby/presenters/weather_stations.rb +60 -0
  923. data/examples/showcase/config/lcp_ruby/presenters/workflow_audit_logs.rb +76 -0
  924. data/examples/showcase/config/lcp_ruby/presenters/workflow_request_audit_zone.rb +28 -0
  925. data/examples/showcase/config/lcp_ruby/theme.yml +2 -0
  926. data/examples/showcase/config/lcp_ruby/types/currency.yml +15 -0
  927. data/examples/showcase/config/lcp_ruby/types/percentage.yml +16 -0
  928. data/examples/showcase/config/lcp_ruby/types/rating.yml +20 -0
  929. data/examples/showcase/config/lcp_ruby/views/announcements.yml +7 -0
  930. data/examples/showcase/config/lcp_ruby/views/approval_requests.yml +7 -0
  931. data/examples/showcase/config/lcp_ruby/views/approval_steps.yml +7 -0
  932. data/examples/showcase/config/lcp_ruby/views/approval_tasks.yml +7 -0
  933. data/examples/showcase/config/lcp_ruby/views/articles.yml +12 -0
  934. data/examples/showcase/config/lcp_ruby/views/authors.yml +7 -0
  935. data/examples/showcase/config/lcp_ruby/views/batch_operation_items.yml +6 -0
  936. data/examples/showcase/config/lcp_ruby/views/batch_operations.yml +10 -0
  937. data/examples/showcase/config/lcp_ruby/views/categories.yml +9 -0
  938. data/examples/showcase/config/lcp_ruby/views/custom_fields.rb +8 -0
  939. data/examples/showcase/config/lcp_ruby/views/dashboard.yml +10 -0
  940. data/examples/showcase/config/lcp_ruby/views/department_explorer.yml +7 -0
  941. data/examples/showcase/config/lcp_ruby/views/departments.yml +9 -0
  942. data/examples/showcase/config/lcp_ruby/views/employee_overview.yml +7 -0
  943. data/examples/showcase/config/lcp_ruby/views/employees.yml +12 -0
  944. data/examples/showcase/config/lcp_ruby/views/export_logs.yml +7 -0
  945. data/examples/showcase/config/lcp_ruby/views/export_profiles.yml +7 -0
  946. data/examples/showcase/config/lcp_ruby/views/features.yml +19 -0
  947. data/examples/showcase/config/lcp_ruby/views/group_memberships.yml +7 -0
  948. data/examples/showcase/config/lcp_ruby/views/group_role_mappings.yml +7 -0
  949. data/examples/showcase/config/lcp_ruby/views/groups.yml +7 -0
  950. data/examples/showcase/config/lcp_ruby/views/host_inventory_items.yml +16 -0
  951. data/examples/showcase/config/lcp_ruby/views/hr_turnover_dashboard.yml +7 -0
  952. data/examples/showcase/config/lcp_ruby/views/import_profiles.yml +7 -0
  953. data/examples/showcase/config/lcp_ruby/views/import_rows.yml +7 -0
  954. data/examples/showcase/config/lcp_ruby/views/lcp_error_logs.yml +10 -0
  955. data/examples/showcase/config/lcp_ruby/views/monitoring.yml +7 -0
  956. data/examples/showcase/config/lcp_ruby/views/my_api_tokens.rb +9 -0
  957. data/examples/showcase/config/lcp_ruby/views/page_configs.yml +11 -0
  958. data/examples/showcase/config/lcp_ruby/views/permission_configs.yml +11 -0
  959. data/examples/showcase/config/lcp_ruby/views/pipeline_stages.yml +7 -0
  960. data/examples/showcase/config/lcp_ruby/views/pipelines.yml +7 -0
  961. data/examples/showcase/config/lcp_ruby/views/platform_profiles.yml +7 -0
  962. data/examples/showcase/config/lcp_ruby/views/projects.yml +9 -0
  963. data/examples/showcase/config/lcp_ruby/views/roles.yml +7 -0
  964. data/examples/showcase/config/lcp_ruby/views/saved_filters.yml +7 -0
  965. data/examples/showcase/config/lcp_ruby/views/showcase_aggregate_items.yml +7 -0
  966. data/examples/showcase/config/lcp_ruby/views/showcase_aggregates.yml +10 -0
  967. data/examples/showcase/config/lcp_ruby/views/showcase_arrays.yml +7 -0
  968. data/examples/showcase/config/lcp_ruby/views/showcase_attachments.yml +7 -0
  969. data/examples/showcase/config/lcp_ruby/views/showcase_audit_logs.yml +11 -0
  970. data/examples/showcase/config/lcp_ruby/views/showcase_audited_records.yml +10 -0
  971. data/examples/showcase/config/lcp_ruby/views/showcase_batch_tasks.yml +10 -0
  972. data/examples/showcase/config/lcp_ruby/views/showcase_business_units.yml +7 -0
  973. data/examples/showcase/config/lcp_ruby/views/showcase_conditions.yml +7 -0
  974. data/examples/showcase/config/lcp_ruby/views/showcase_contacts.yml +7 -0
  975. data/examples/showcase/config/lcp_ruby/views/showcase_custom_render_with.yml +7 -0
  976. data/examples/showcase/config/lcp_ruby/views/showcase_custom_sections.yml +7 -0
  977. data/examples/showcase/config/lcp_ruby/views/showcase_custom_zones.yml +7 -0
  978. data/examples/showcase/config/lcp_ruby/views/showcase_divisions.yml +9 -0
  979. data/examples/showcase/config/lcp_ruby/views/showcase_extensibility.yml +7 -0
  980. data/examples/showcase/config/lcp_ruby/views/showcase_fields.yml +13 -0
  981. data/examples/showcase/config/lcp_ruby/views/showcase_form_actions.yml +10 -0
  982. data/examples/showcase/config/lcp_ruby/views/showcase_forms.yml +7 -0
  983. data/examples/showcase/config/lcp_ruby/views/showcase_grades.yml +9 -0
  984. data/examples/showcase/config/lcp_ruby/views/showcase_hr_employees.yml +9 -0
  985. data/examples/showcase/config/lcp_ruby/views/showcase_item_classes.yml +7 -0
  986. data/examples/showcase/config/lcp_ruby/views/showcase_job_executions.yml +9 -0
  987. data/examples/showcase/config/lcp_ruby/views/showcase_memos.yml +7 -0
  988. data/examples/showcase/config/lcp_ruby/views/showcase_models.yml +7 -0
  989. data/examples/showcase/config/lcp_ruby/views/showcase_organizations.yml +7 -0
  990. data/examples/showcase/config/lcp_ruby/views/showcase_people.yml +7 -0
  991. data/examples/showcase/config/lcp_ruby/views/showcase_permissions.yml +7 -0
  992. data/examples/showcase/config/lcp_ruby/views/showcase_positioning.yml +7 -0
  993. data/examples/showcase/config/lcp_ruby/views/showcase_recipes.yml +10 -0
  994. data/examples/showcase/config/lcp_ruby/views/showcase_reports.yml +7 -0
  995. data/examples/showcase/config/lcp_ruby/views/showcase_school_classes.yml +7 -0
  996. data/examples/showcase/config/lcp_ruby/views/showcase_searches.yml +7 -0
  997. data/examples/showcase/config/lcp_ruby/views/showcase_sequences.yml +7 -0
  998. data/examples/showcase/config/lcp_ruby/views/showcase_soft_delete.yml +10 -0
  999. data/examples/showcase/config/lcp_ruby/views/showcase_soft_delete_items.yml +8 -0
  1000. data/examples/showcase/config/lcp_ruby/views/showcase_students.yml +9 -0
  1001. data/examples/showcase/config/lcp_ruby/views/showcase_userstamps.yml +7 -0
  1002. data/examples/showcase/config/lcp_ruby/views/showcase_virtual_fields.yml +7 -0
  1003. data/examples/showcase/config/lcp_ruby/views/showcase_workflows.yml +16 -0
  1004. data/examples/showcase/config/lcp_ruby/views/tags.yml +7 -0
  1005. data/examples/showcase/config/lcp_ruby/views/users.yml +7 -0
  1006. data/examples/showcase/config/lcp_ruby/views/weather_stations.yml +7 -0
  1007. data/examples/showcase/config/lcp_ruby/views/workflow_audit_logs.yml +9 -0
  1008. data/examples/showcase/config/lcp_ruby/workflows/showcase_form_action.rb +48 -0
  1009. data/examples/showcase/config/lcp_ruby/workflows/showcase_workflow.rb +199 -0
  1010. data/examples/showcase/config/locales/cs.yml +2818 -0
  1011. data/examples/showcase/config/locales/en.yml +67 -0
  1012. data/examples/showcase/config/locales/lcp_ruby/api_tokens.cs.yml +46 -0
  1013. data/examples/showcase/config/locales/lcp_ruby/api_tokens.en.yml +49 -0
  1014. data/examples/showcase/config/routes.rb +21 -0
  1015. data/examples/showcase/config/storage.yml +3 -0
  1016. data/examples/showcase/config.ru +2 -0
  1017. data/examples/showcase/db/migrate/20260219124321_create_active_storage_tables.active_storage.rb +57 -0
  1018. data/examples/showcase/db/migrate/20260220072723_create_lcp_ruby_users.rb +42 -0
  1019. data/examples/showcase/db/migrate/20260406120000_create_host_inventory_items.rb +32 -0
  1020. data/examples/showcase/db/migrate/20260428134542_add_oidc_columns_to_lcp_ruby_users.rb +13 -0
  1021. data/examples/showcase/db/migrate/20260502120000_create_platform_profiles.rb +19 -0
  1022. data/examples/showcase/db/schema.rb +1222 -0
  1023. data/examples/showcase/db/seeds.rb +3085 -0
  1024. data/examples/showcase/erd.md +567 -0
  1025. data/examples/showcase/test/fixtures/import_articles.csv +4 -0
  1026. data/examples/showcase/test/fixtures/import_employees.csv +4 -0
  1027. data/examples/todo/Gemfile +8 -0
  1028. data/examples/todo/Gemfile.lock +415 -0
  1029. data/examples/todo/Rakefile +2 -0
  1030. data/examples/todo/app/assets/config/manifest.js +1 -0
  1031. data/examples/todo/app/controllers/application_controller.rb +6 -0
  1032. data/examples/todo/app/lcp_services/defaults/one_week_from_now.rb +11 -0
  1033. data/examples/todo/bin/rails +4 -0
  1034. data/examples/todo/bin/rake +4 -0
  1035. data/examples/todo/config/application.rb +31 -0
  1036. data/examples/todo/config/boot.rb +2 -0
  1037. data/examples/todo/config/database.yml +12 -0
  1038. data/examples/todo/config/environment.rb +2 -0
  1039. data/examples/todo/config/lcp_ruby/models/todo_item.yml +67 -0
  1040. data/examples/todo/config/lcp_ruby/models/todo_list.yml +49 -0
  1041. data/examples/todo/config/lcp_ruby/permissions/default.yml +10 -0
  1042. data/examples/todo/config/lcp_ruby/permissions/todo_item.yml +21 -0
  1043. data/examples/todo/config/lcp_ruby/presenters/todo_item.yml +75 -0
  1044. data/examples/todo/config/lcp_ruby/presenters/todo_list.yml +68 -0
  1045. data/examples/todo/config/lcp_ruby/views/todo_items.yml +11 -0
  1046. data/examples/todo/config/lcp_ruby/views/todo_lists.yml +9 -0
  1047. data/examples/todo/config/routes.rb +4 -0
  1048. data/examples/todo/config/storage.yml +3 -0
  1049. data/examples/todo/config.ru +2 -0
  1050. data/examples/todo/db/migrate/20260219103416_create_active_storage_tables.active_storage.rb +57 -0
  1051. data/examples/todo/db/schema.rb +63 -0
  1052. data/examples/todo/db/seeds.rb +24 -0
  1053. data/examples/todo/erd.md +21 -0
  1054. data/exe/lcp +33 -0
  1055. data/lib/generators/lcp_ruby/agent_setup_generator.rb +102 -0
  1056. data/lib/generators/lcp_ruby/api_tokens_generator.rb +102 -0
  1057. data/lib/generators/lcp_ruby/auditing_generator.rb +54 -0
  1058. data/lib/generators/lcp_ruby/background_jobs_generator.rb +61 -0
  1059. data/lib/generators/lcp_ruby/batch_operations_generator.rb +62 -0
  1060. data/lib/generators/lcp_ruby/claude_skills_generator.rb +47 -0
  1061. data/lib/generators/lcp_ruby/custom_fields_generator.rb +54 -0
  1062. data/lib/generators/lcp_ruby/dsl_to_yaml.rb +72 -0
  1063. data/lib/generators/lcp_ruby/entity/color_palette.rb +22 -0
  1064. data/lib/generators/lcp_ruby/entity/field_descriptor.rb +24 -0
  1065. data/lib/generators/lcp_ruby/entity/field_token_parser.rb +101 -0
  1066. data/lib/generators/lcp_ruby/entity/role_discovery.rb +45 -0
  1067. data/lib/generators/lcp_ruby/entity_generator.rb +1104 -0
  1068. data/lib/generators/lcp_ruby/export_generator.rb +71 -0
  1069. data/lib/generators/lcp_ruby/format_support.rb +56 -0
  1070. data/lib/generators/lcp_ruby/gapfree_sequences_generator.rb +64 -0
  1071. data/lib/generators/lcp_ruby/groups_generator.rb +94 -0
  1072. data/lib/generators/lcp_ruby/host_controller_generator.rb +202 -0
  1073. data/lib/generators/lcp_ruby/import_generator.rb +96 -0
  1074. data/lib/generators/lcp_ruby/install_auth_generator.rb +432 -0
  1075. data/lib/generators/lcp_ruby/install_generator.rb +319 -0
  1076. data/lib/generators/lcp_ruby/monitoring_generator.rb +58 -0
  1077. data/lib/generators/lcp_ruby/oidc_role_mappings_generator.rb +60 -0
  1078. data/lib/generators/lcp_ruby/pages_generator.rb +66 -0
  1079. data/lib/generators/lcp_ruby/permission_source_generator.rb +66 -0
  1080. data/lib/generators/lcp_ruby/role_model_generator.rb +73 -0
  1081. data/lib/generators/lcp_ruby/saved_filters_generator.rb +62 -0
  1082. data/lib/generators/lcp_ruby/templates/add_oidc_columns_to_lcp_ruby_users.rb.erb +13 -0
  1083. data/lib/generators/lcp_ruby/templates/agent_setup/agents_md.md +3 -0
  1084. data/lib/generators/lcp_ruby/templates/agent_setup/claude_md.md +12 -0
  1085. data/lib/generators/lcp_ruby/templates/api_tokens/create_dialog.rb +31 -0
  1086. data/lib/generators/lcp_ruby/templates/api_tokens/locales.en.yml +43 -0
  1087. data/lib/generators/lcp_ruby/templates/api_tokens/model.rb +23 -0
  1088. data/lib/generators/lcp_ruby/templates/api_tokens/permissions.yml +30 -0
  1089. data/lib/generators/lcp_ruby/templates/api_tokens/presenter.rb +38 -0
  1090. data/lib/generators/lcp_ruby/templates/api_tokens/view_group.rb +13 -0
  1091. data/lib/generators/lcp_ruby/templates/auditing/model.rb +34 -0
  1092. data/lib/generators/lcp_ruby/templates/auditing/permissions.yml +19 -0
  1093. data/lib/generators/lcp_ruby/templates/auditing/presenter.rb +41 -0
  1094. data/lib/generators/lcp_ruby/templates/auditing/view_group.rb +10 -0
  1095. data/lib/generators/lcp_ruby/templates/background_jobs/model.rb +59 -0
  1096. data/lib/generators/lcp_ruby/templates/background_jobs/permissions.yml +22 -0
  1097. data/lib/generators/lcp_ruby/templates/background_jobs/presenter.rb +82 -0
  1098. data/lib/generators/lcp_ruby/templates/background_jobs/view_group.rb +9 -0
  1099. data/lib/generators/lcp_ruby/templates/batch_operations/item_model.rb +28 -0
  1100. data/lib/generators/lcp_ruby/templates/batch_operations/item_presenter.rb +43 -0
  1101. data/lib/generators/lcp_ruby/templates/batch_operations/model.rb +42 -0
  1102. data/lib/generators/lcp_ruby/templates/batch_operations/permissions.yml +44 -0
  1103. data/lib/generators/lcp_ruby/templates/batch_operations/presenter.rb +61 -0
  1104. data/lib/generators/lcp_ruby/templates/batch_operations/view_group.rb +9 -0
  1105. data/lib/generators/lcp_ruby/templates/create_lcp_ruby_users.rb.erb +50 -0
  1106. data/lib/generators/lcp_ruby/templates/custom_fields/model.rb +60 -0
  1107. data/lib/generators/lcp_ruby/templates/custom_fields/permissions.yml +19 -0
  1108. data/lib/generators/lcp_ruby/templates/custom_fields/presenter.rb +128 -0
  1109. data/lib/generators/lcp_ruby/templates/custom_fields/view_group.rb +9 -0
  1110. data/lib/generators/lcp_ruby/templates/entity/model.rb +42 -0
  1111. data/lib/generators/lcp_ruby/templates/entity/permissions.yml +20 -0
  1112. data/lib/generators/lcp_ruby/templates/entity/presenter.rb +55 -0
  1113. data/lib/generators/lcp_ruby/templates/entity/view_group.rb +8 -0
  1114. data/lib/generators/lcp_ruby/templates/export/export_log_model.rb +30 -0
  1115. data/lib/generators/lcp_ruby/templates/export/export_log_permissions.yml +24 -0
  1116. data/lib/generators/lcp_ruby/templates/export/export_logs_presenter.rb +51 -0
  1117. data/lib/generators/lcp_ruby/templates/export/export_profile_model.rb +28 -0
  1118. data/lib/generators/lcp_ruby/templates/export/export_profile_permissions.yml +26 -0
  1119. data/lib/generators/lcp_ruby/templates/export/export_profiles_presenter.rb +59 -0
  1120. data/lib/generators/lcp_ruby/templates/gapfree_sequences/model.rb +18 -0
  1121. data/lib/generators/lcp_ruby/templates/gapfree_sequences/permissions.yml +19 -0
  1122. data/lib/generators/lcp_ruby/templates/gapfree_sequences/presenter.rb +51 -0
  1123. data/lib/generators/lcp_ruby/templates/gapfree_sequences/view_group.rb +9 -0
  1124. data/lib/generators/lcp_ruby/templates/groups/group_membership_model.rb +17 -0
  1125. data/lib/generators/lcp_ruby/templates/groups/group_model.rb +28 -0
  1126. data/lib/generators/lcp_ruby/templates/groups/group_permissions.yml +19 -0
  1127. data/lib/generators/lcp_ruby/templates/groups/group_presenter.rb +53 -0
  1128. data/lib/generators/lcp_ruby/templates/groups/group_role_mapping_model.rb +15 -0
  1129. data/lib/generators/lcp_ruby/templates/groups/group_view_group.rb +9 -0
  1130. data/lib/generators/lcp_ruby/templates/host_controller/controller.rb.erb +131 -0
  1131. data/lib/generators/lcp_ruby/templates/import/data_import_job.yml +7 -0
  1132. data/lib/generators/lcp_ruby/templates/import/import_profile_model.rb +30 -0
  1133. data/lib/generators/lcp_ruby/templates/import/import_profile_permissions.yml +29 -0
  1134. data/lib/generators/lcp_ruby/templates/import/import_profiles_presenter.rb +57 -0
  1135. data/lib/generators/lcp_ruby/templates/import/import_row_model.rb +32 -0
  1136. data/lib/generators/lcp_ruby/templates/import/import_row_permissions.yml +11 -0
  1137. data/lib/generators/lcp_ruby/templates/import/import_rows_presenter.rb +35 -0
  1138. data/lib/generators/lcp_ruby/templates/install/default_permissions.yml +26 -0
  1139. data/lib/generators/lcp_ruby/templates/install/menu.yml.tt +71 -0
  1140. data/lib/generators/lcp_ruby/templates/install/model.rb +20 -0
  1141. data/lib/generators/lcp_ruby/templates/install/permissions.yml +25 -0
  1142. data/lib/generators/lcp_ruby/templates/install/presenter.rb +44 -0
  1143. data/lib/generators/lcp_ruby/templates/install/view_group.rb +10 -0
  1144. data/lib/generators/lcp_ruby/templates/install_auth/oidc/entra.yml.erb +46 -0
  1145. data/lib/generators/lcp_ruby/templates/install_auth/oidc/generic.yml.erb +55 -0
  1146. data/lib/generators/lcp_ruby/templates/install_auth/oidc/google.yml.erb +42 -0
  1147. data/lib/generators/lcp_ruby/templates/install_auth/oidc/keycloak.yml.erb +45 -0
  1148. data/lib/generators/lcp_ruby/templates/install_auth/oidc/okta.yml.erb +45 -0
  1149. data/lib/generators/lcp_ruby/templates/install_auth/user.rb +36 -0
  1150. data/lib/generators/lcp_ruby/templates/monitoring/model.rb +34 -0
  1151. data/lib/generators/lcp_ruby/templates/monitoring/model_extension.rb +12 -0
  1152. data/lib/generators/lcp_ruby/templates/monitoring/page.yml +49 -0
  1153. data/lib/generators/lcp_ruby/templates/monitoring/permissions.yml +8 -0
  1154. data/lib/generators/lcp_ruby/templates/monitoring/presenter.rb +44 -0
  1155. data/lib/generators/lcp_ruby/templates/oidc_role_mappings/locales.en.yml +15 -0
  1156. data/lib/generators/lcp_ruby/templates/oidc_role_mappings/model.rb +32 -0
  1157. data/lib/generators/lcp_ruby/templates/oidc_role_mappings/permissions.yml +21 -0
  1158. data/lib/generators/lcp_ruby/templates/oidc_role_mappings/presenter.rb +41 -0
  1159. data/lib/generators/lcp_ruby/templates/pages/model.rb +19 -0
  1160. data/lib/generators/lcp_ruby/templates/pages/permissions.yml +19 -0
  1161. data/lib/generators/lcp_ruby/templates/pages/presenter.rb +51 -0
  1162. data/lib/generators/lcp_ruby/templates/pages/view_group.rb +10 -0
  1163. data/lib/generators/lcp_ruby/templates/permission_source/model.rb +21 -0
  1164. data/lib/generators/lcp_ruby/templates/permission_source/permissions.yml +19 -0
  1165. data/lib/generators/lcp_ruby/templates/permission_source/presenter.rb +51 -0
  1166. data/lib/generators/lcp_ruby/templates/permission_source/view_group.rb +10 -0
  1167. data/lib/generators/lcp_ruby/templates/role_model/model.rb +24 -0
  1168. data/lib/generators/lcp_ruby/templates/role_model/permissions.yml +19 -0
  1169. data/lib/generators/lcp_ruby/templates/role_model/presenter.rb +62 -0
  1170. data/lib/generators/lcp_ruby/templates/role_model/view_group.rb +10 -0
  1171. data/lib/generators/lcp_ruby/templates/saved_filters/model.rb +51 -0
  1172. data/lib/generators/lcp_ruby/templates/saved_filters/permissions.yml +44 -0
  1173. data/lib/generators/lcp_ruby/templates/saved_filters/presenter.rb +96 -0
  1174. data/lib/generators/lcp_ruby/templates/saved_filters/save_dialog_presenter.rb +19 -0
  1175. data/lib/generators/lcp_ruby/templates/workflow_approvals/request_model.rb +50 -0
  1176. data/lib/generators/lcp_ruby/templates/workflow_approvals/request_permissions.yml +10 -0
  1177. data/lib/generators/lcp_ruby/templates/workflow_approvals/request_presenter.rb +44 -0
  1178. data/lib/generators/lcp_ruby/templates/workflow_approvals/request_view_group.rb +10 -0
  1179. data/lib/generators/lcp_ruby/templates/workflow_approvals/step_model.rb +36 -0
  1180. data/lib/generators/lcp_ruby/templates/workflow_approvals/step_permissions.yml +10 -0
  1181. data/lib/generators/lcp_ruby/templates/workflow_approvals/task_model.rb +34 -0
  1182. data/lib/generators/lcp_ruby/templates/workflow_approvals/task_permissions.yml +10 -0
  1183. data/lib/generators/lcp_ruby/templates/workflow_approvals/task_presenter.rb +39 -0
  1184. data/lib/generators/lcp_ruby/templates/workflow_approvals/task_view_group.rb +10 -0
  1185. data/lib/generators/lcp_ruby/templates/workflow_audit_log/model.rb +48 -0
  1186. data/lib/generators/lcp_ruby/templates/workflow_audit_log/permissions.yml +10 -0
  1187. data/lib/generators/lcp_ruby/templates/workflow_audit_log/presenter.rb +44 -0
  1188. data/lib/generators/lcp_ruby/templates/workflow_audit_log/view_group.rb +10 -0
  1189. data/lib/generators/lcp_ruby/templates/workflow_definition/model.rb +43 -0
  1190. data/lib/generators/lcp_ruby/templates/workflow_definition/permissions.yml +19 -0
  1191. data/lib/generators/lcp_ruby/templates/workflow_definition/presenter.rb +70 -0
  1192. data/lib/generators/lcp_ruby/templates/workflow_definition/view_group.rb +10 -0
  1193. data/lib/generators/lcp_ruby/workflow_approvals_generator.rb +93 -0
  1194. data/lib/generators/lcp_ruby/workflow_audit_log_generator.rb +54 -0
  1195. data/lib/generators/lcp_ruby/workflow_definition_generator.rb +77 -0
  1196. data/lib/lcp.rb +6 -0
  1197. data/lib/lcp_ruby/actions/action_executor.rb +66 -0
  1198. data/lib/lcp_ruby/actions/action_registry.rb +48 -0
  1199. data/lib/lcp_ruby/actions/api_tokens/revoke.rb +13 -0
  1200. data/lib/lcp_ruby/actions/base_action.rb +79 -0
  1201. data/lib/lcp_ruby/actions/form_action_pipeline.rb +138 -0
  1202. data/lib/lcp_ruby/aggregates/query_builder.rb +6 -0
  1203. data/lib/lcp_ruby/api_tokens/model_extension.rb +41 -0
  1204. data/lib/lcp_ruby/api_tokens/resolver_registry.rb +53 -0
  1205. data/lib/lcp_ruby/api_tokens/token_generator.rb +27 -0
  1206. data/lib/lcp_ruby/api_tokens/verifier.rb +38 -0
  1207. data/lib/lcp_ruby/app_template.rb +181 -0
  1208. data/lib/lcp_ruby/array_query.rb +120 -0
  1209. data/lib/lcp_ruby/asset_copier.rb +62 -0
  1210. data/lib/lcp_ruby/association_fk_type.rb +191 -0
  1211. data/lib/lcp_ruby/association_join_column.rb +28 -0
  1212. data/lib/lcp_ruby/association_options_builder.rb +231 -0
  1213. data/lib/lcp_ruby/auditing/audit_writer.rb +258 -0
  1214. data/lib/lcp_ruby/auditing/contract_validator.rb +95 -0
  1215. data/lib/lcp_ruby/auditing/registry.rb +29 -0
  1216. data/lib/lcp_ruby/auditing/setup.rb +49 -0
  1217. data/lib/lcp_ruby/authentication/audit_subscriber.rb +51 -0
  1218. data/lib/lcp_ruby/authentication/bearer_jwt_verifier.rb +139 -0
  1219. data/lib/lcp_ruby/authentication/devise_setup.rb +47 -0
  1220. data/lib/lcp_ruby/authentication/errors.rb +27 -0
  1221. data/lib/lcp_ruby/authentication/http_fetcher.rb +36 -0
  1222. data/lib/lcp_ruby/authentication/jwks_cache.rb +91 -0
  1223. data/lib/lcp_ruby/authentication/oidc_bearer_resolver.rb +84 -0
  1224. data/lib/lcp_ruby/authentication/omniauth_builder.rb +147 -0
  1225. data/lib/lcp_ruby/authentication/provider.rb +108 -0
  1226. data/lib/lcp_ruby/authentication/provider_registry.rb +227 -0
  1227. data/lib/lcp_ruby/authentication/role_mapper.rb +94 -0
  1228. data/lib/lcp_ruby/authentication/test_support.rb +257 -0
  1229. data/lib/lcp_ruby/authentication/user_resolver.rb +169 -0
  1230. data/lib/lcp_ruby/authentication.rb +40 -0
  1231. data/lib/lcp_ruby/authorization/association_lookup.rb +56 -0
  1232. data/lib/lcp_ruby/authorization/authorization_error.rb +12 -0
  1233. data/lib/lcp_ruby/authorization/cache.rb +89 -0
  1234. data/lib/lcp_ruby/authorization/codes.rb +17 -0
  1235. data/lib/lcp_ruby/authorization/impersonated_user.rb +29 -0
  1236. data/lib/lcp_ruby/authorization/includes_hint.rb +110 -0
  1237. data/lib/lcp_ruby/authorization/inherited_parent_validator.rb +142 -0
  1238. data/lib/lcp_ruby/authorization/invariant_check/configuration.rb +132 -0
  1239. data/lib/lcp_ruby/authorization/invariant_error.rb +15 -0
  1240. data/lib/lcp_ruby/authorization/misconfigured_page_error.rb +30 -0
  1241. data/lib/lcp_ruby/authorization/page_gate.rb +57 -0
  1242. data/lib/lcp_ruby/authorization/permission_evaluator.rb +343 -0
  1243. data/lib/lcp_ruby/authorization/policy_factory.rb +91 -0
  1244. data/lib/lcp_ruby/authorization/runtime_invariant_validator.rb +421 -0
  1245. data/lib/lcp_ruby/authorization/scope_builder.rb +227 -0
  1246. data/lib/lcp_ruby/authorization/scope_resolver.rb +28 -0
  1247. data/lib/lcp_ruby/authorized_controller.rb +44 -0
  1248. data/lib/lcp_ruby/background_jobs/base_handler.rb +113 -0
  1249. data/lib/lcp_ruby/background_jobs/change_handler.rb +17 -0
  1250. data/lib/lcp_ruby/background_jobs/contract.rb +16 -0
  1251. data/lib/lcp_ruby/background_jobs/contract_validator.rb +112 -0
  1252. data/lib/lcp_ruby/background_jobs/declarative/base_action.rb +11 -0
  1253. data/lib/lcp_ruby/background_jobs/declarative/call_webhook_action.rb +174 -0
  1254. data/lib/lcp_ruby/background_jobs/declarative/fire_event_action.rb +24 -0
  1255. data/lib/lcp_ruby/background_jobs/declarative/registry.rb +34 -0
  1256. data/lib/lcp_ruby/background_jobs/declarative/run_scope_action.rb +98 -0
  1257. data/lib/lcp_ruby/background_jobs/declarative/send_notification_action.rb +13 -0
  1258. data/lib/lcp_ruby/background_jobs/definition.rb +134 -0
  1259. data/lib/lcp_ruby/background_jobs/enqueue.rb +83 -0
  1260. data/lib/lcp_ruby/background_jobs/errors.rb +9 -0
  1261. data/lib/lcp_ruby/background_jobs/executor_job.rb +111 -0
  1262. data/lib/lcp_ruby/background_jobs/handler_factory.rb +46 -0
  1263. data/lib/lcp_ruby/background_jobs/host_source.rb +33 -0
  1264. data/lib/lcp_ruby/background_jobs/model_source.rb +93 -0
  1265. data/lib/lcp_ruby/background_jobs/registry.rb +81 -0
  1266. data/lib/lcp_ruby/background_jobs/resolver.rb +29 -0
  1267. data/lib/lcp_ruby/background_jobs/schedule_adapter.rb +14 -0
  1268. data/lib/lcp_ruby/background_jobs/setup.rb +145 -0
  1269. data/lib/lcp_ruby/background_jobs/static_source.rb +19 -0
  1270. data/lib/lcp_ruby/background_jobs/steps_executor.rb +52 -0
  1271. data/lib/lcp_ruby/background_jobs/triggers/event_trigger.rb +97 -0
  1272. data/lib/lcp_ruby/background_jobs/triggers/trigger_installer.rb +20 -0
  1273. data/lib/lcp_ruby/background_jobs/unique_key_builder.rb +31 -0
  1274. data/lib/lcp_ruby/batch_actions/base_service.rb +70 -0
  1275. data/lib/lcp_ruby/batch_actions/batch_action_handler.rb +200 -0
  1276. data/lib/lcp_ruby/batch_actions/custom_action_dispatcher.rb +133 -0
  1277. data/lib/lcp_ruby/batch_actions/destroy_service.rb +37 -0
  1278. data/lib/lcp_ruby/batch_actions/permanently_destroy_service.rb +33 -0
  1279. data/lib/lcp_ruby/batch_actions/restore_service.rb +33 -0
  1280. data/lib/lcp_ruby/batch_actions.rb +5 -0
  1281. data/lib/lcp_ruby/bulk_updater.rb +25 -0
  1282. data/lib/lcp_ruby/cli/docs_command.rb +29 -0
  1283. data/lib/lcp_ruby/cli/examples_command.rb +29 -0
  1284. data/lib/lcp_ruby/cli/new_command.rb +509 -0
  1285. data/lib/lcp_ruby/cli/run_command.rb +155 -0
  1286. data/lib/lcp_ruby/cli/skills_command.rb +54 -0
  1287. data/lib/lcp_ruby/cli.rb +74 -0
  1288. data/lib/lcp_ruby/condition_evaluator.rb +366 -0
  1289. data/lib/lcp_ruby/condition_service_registry.rb +58 -0
  1290. data/lib/lcp_ruby/condition_services/current_user_role.rb +28 -0
  1291. data/lib/lcp_ruby/condition_services/feature_flag.rb +63 -0
  1292. data/lib/lcp_ruby/condition_services/impersonating.rb +24 -0
  1293. data/lib/lcp_ruby/conditions/validator.rb +35 -0
  1294. data/lib/lcp_ruby/configuration.rb +431 -0
  1295. data/lib/lcp_ruby/controller/authentication.rb +118 -0
  1296. data/lib/lcp_ruby/controller/authorization.rb +198 -0
  1297. data/lib/lcp_ruby/controller/bearer_authentication.rb +76 -0
  1298. data/lib/lcp_ruby/controller/crud_helpers.rb +233 -0
  1299. data/lib/lcp_ruby/controller/error_handling.rb +94 -0
  1300. data/lib/lcp_ruby/controller/impersonation.rb +70 -0
  1301. data/lib/lcp_ruby/controller/locale_binding.rb +62 -0
  1302. data/lib/lcp_ruby/controller/path_helpers.rb +125 -0
  1303. data/lib/lcp_ruby/controller/presenter_setup.rb +89 -0
  1304. data/lib/lcp_ruby/controller/search.rb +321 -0
  1305. data/lib/lcp_ruby/controller/view_helpers.rb +105 -0
  1306. data/lib/lcp_ruby/current.rb +13 -0
  1307. data/lib/lcp_ruby/custom_fields/applicator.rb +194 -0
  1308. data/lib/lcp_ruby/custom_fields/contract_validator.rb +77 -0
  1309. data/lib/lcp_ruby/custom_fields/definition_change_handler.rb +21 -0
  1310. data/lib/lcp_ruby/custom_fields/query.rb +112 -0
  1311. data/lib/lcp_ruby/custom_fields/registry.rb +70 -0
  1312. data/lib/lcp_ruby/custom_fields/setup.rb +58 -0
  1313. data/lib/lcp_ruby/custom_fields/utils.rb +40 -0
  1314. data/lib/lcp_ruby/custom_fields.rb +9 -0
  1315. data/lib/lcp_ruby/data_source/api_error_placeholder.rb +47 -0
  1316. data/lib/lcp_ruby/data_source/api_filter_translator.rb +72 -0
  1317. data/lib/lcp_ruby/data_source/api_model_concern.rb +131 -0
  1318. data/lib/lcp_ruby/data_source/api_preloader.rb +44 -0
  1319. data/lib/lcp_ruby/data_source/base.rb +85 -0
  1320. data/lib/lcp_ruby/data_source/cached_wrapper.rb +107 -0
  1321. data/lib/lcp_ruby/data_source/host.rb +71 -0
  1322. data/lib/lcp_ruby/data_source/registry.rb +39 -0
  1323. data/lib/lcp_ruby/data_source/resilient_wrapper.rb +67 -0
  1324. data/lib/lcp_ruby/data_source/rest_json.rb +247 -0
  1325. data/lib/lcp_ruby/data_source/setup.rb +57 -0
  1326. data/lib/lcp_ruby/dev_toolbar.rb +8 -0
  1327. data/lib/lcp_ruby/display/base_renderer.rb +21 -0
  1328. data/lib/lcp_ruby/display/count_badge.rb +11 -0
  1329. data/lib/lcp_ruby/display/icon_badge.rb +17 -0
  1330. data/lib/lcp_ruby/display/renderer_registry.rb +138 -0
  1331. data/lib/lcp_ruby/display/renderers/attachment_link.rb +26 -0
  1332. data/lib/lcp_ruby/display/renderers/attachment_list.rb +32 -0
  1333. data/lib/lcp_ruby/display/renderers/attachment_preview.rb +26 -0
  1334. data/lib/lcp_ruby/display/renderers/avatar.rb +14 -0
  1335. data/lib/lcp_ruby/display/renderers/badge.rb +43 -0
  1336. data/lib/lcp_ruby/display/renderers/boolean_icon.rb +54 -0
  1337. data/lib/lcp_ruby/display/renderers/code.rb +39 -0
  1338. data/lib/lcp_ruby/display/renderers/collection.rb +34 -0
  1339. data/lib/lcp_ruby/display/renderers/color_swatch.rb +25 -0
  1340. data/lib/lcp_ruby/display/renderers/concerns/attachment_helpers.rb +73 -0
  1341. data/lib/lcp_ruby/display/renderers/concerns/workflow_helpers.rb +35 -0
  1342. data/lib/lcp_ruby/display/renderers/copy_code.rb +33 -0
  1343. data/lib/lcp_ruby/display/renderers/currency.rb +14 -0
  1344. data/lib/lcp_ruby/display/renderers/date.rb +17 -0
  1345. data/lib/lcp_ruby/display/renderers/datetime.rb +17 -0
  1346. data/lib/lcp_ruby/display/renderers/email_link.rb +15 -0
  1347. data/lib/lcp_ruby/display/renderers/file_size.rb +11 -0
  1348. data/lib/lcp_ruby/display/renderers/heading.rb +11 -0
  1349. data/lib/lcp_ruby/display/renderers/image.rb +17 -0
  1350. data/lib/lcp_ruby/display/renderers/internal_link.rb +23 -0
  1351. data/lib/lcp_ruby/display/renderers/link.rb +15 -0
  1352. data/lib/lcp_ruby/display/renderers/link_list.rb +90 -0
  1353. data/lib/lcp_ruby/display/renderers/markdown.rb +33 -0
  1354. data/lib/lcp_ruby/display/renderers/number.rb +14 -0
  1355. data/lib/lcp_ruby/display/renderers/percentage.rb +12 -0
  1356. data/lib/lcp_ruby/display/renderers/phone_link.rb +15 -0
  1357. data/lib/lcp_ruby/display/renderers/progress_bar.rb +15 -0
  1358. data/lib/lcp_ruby/display/renderers/rating.rb +15 -0
  1359. data/lib/lcp_ruby/display/renderers/record_link.rb +101 -0
  1360. data/lib/lcp_ruby/display/renderers/relative_date.rb +15 -0
  1361. data/lib/lcp_ruby/display/renderers/rich_text.rb +15 -0
  1362. data/lib/lcp_ruby/display/renderers/text.rb +12 -0
  1363. data/lib/lcp_ruby/display/renderers/truncate.rb +17 -0
  1364. data/lib/lcp_ruby/display/renderers/url_link.rb +22 -0
  1365. data/lib/lcp_ruby/display/renderers/workflow_badge.rb +37 -0
  1366. data/lib/lcp_ruby/display/renderers/workflow_timeline.rb +173 -0
  1367. data/lib/lcp_ruby/display/renderers.rb +3 -0
  1368. data/lib/lcp_ruby/display/text_badge.rb +15 -0
  1369. data/lib/lcp_ruby/dsl/condition_builder.rb +190 -0
  1370. data/lib/lcp_ruby/dsl/dsl_loader.rb +365 -0
  1371. data/lib/lcp_ruby/dsl/field_builder.rb +35 -0
  1372. data/lib/lcp_ruby/dsl/job_builder.rb +92 -0
  1373. data/lib/lcp_ruby/dsl/model_builder.rb +544 -0
  1374. data/lib/lcp_ruby/dsl/presenter_builder.rb +1272 -0
  1375. data/lib/lcp_ruby/dsl/source_location_capture.rb +52 -0
  1376. data/lib/lcp_ruby/dsl/type_builder.rb +88 -0
  1377. data/lib/lcp_ruby/dsl/view_group_builder.rb +92 -0
  1378. data/lib/lcp_ruby/dsl/workflow_builder.rb +319 -0
  1379. data/lib/lcp_ruby/dynamic.rb +7 -0
  1380. data/lib/lcp_ruby/dynamic_references/resolver.rb +154 -0
  1381. data/lib/lcp_ruby/dynamic_references/validator.rb +92 -0
  1382. data/lib/lcp_ruby/embed_providers/base.rb +18 -0
  1383. data/lib/lcp_ruby/embed_providers/grafana.rb +38 -0
  1384. data/lib/lcp_ruby/embed_providers/metabase.rb +37 -0
  1385. data/lib/lcp_ruby/engine.rb +680 -0
  1386. data/lib/lcp_ruby/events/async_handler_job.rb +21 -0
  1387. data/lib/lcp_ruby/events/dispatcher.rb +52 -0
  1388. data/lib/lcp_ruby/events/handler_base.rb +51 -0
  1389. data/lib/lcp_ruby/events/handler_registry.rb +49 -0
  1390. data/lib/lcp_ruby/export/data_generator.rb +158 -0
  1391. data/lib/lcp_ruby/export/export_handler.rb +315 -0
  1392. data/lib/lcp_ruby/export/field_tree_builder.rb +219 -0
  1393. data/lib/lcp_ruby/export/setup.rb +94 -0
  1394. data/lib/lcp_ruby/export/value_formatter.rb +223 -0
  1395. data/lib/lcp_ruby/export.rb +9 -0
  1396. data/lib/lcp_ruby/gem_paths.rb +51 -0
  1397. data/lib/lcp_ruby/generators/entity_menu_writer.rb +258 -0
  1398. data/lib/lcp_ruby/generators/feature_registry.rb +208 -0
  1399. data/lib/lcp_ruby/generators/prerequisites.rb +90 -0
  1400. data/lib/lcp_ruby/grouped_query/builder.rb +206 -0
  1401. data/lib/lcp_ruby/grouped_query/result_wrapper.rb +72 -0
  1402. data/lib/lcp_ruby/grouped_query/row.rb +31 -0
  1403. data/lib/lcp_ruby/groups/change_handler.rb +18 -0
  1404. data/lib/lcp_ruby/groups/contract.rb +42 -0
  1405. data/lib/lcp_ruby/groups/contract_validator.rb +110 -0
  1406. data/lib/lcp_ruby/groups/host_loader.rb +54 -0
  1407. data/lib/lcp_ruby/groups/model_loader.rb +186 -0
  1408. data/lib/lcp_ruby/groups/registry.rb +113 -0
  1409. data/lib/lcp_ruby/groups/setup.rb +129 -0
  1410. data/lib/lcp_ruby/groups/yaml_loader.rb +97 -0
  1411. data/lib/lcp_ruby/hash_utils.rb +42 -0
  1412. data/lib/lcp_ruby/i18n_check/configuration.rb +104 -0
  1413. data/lib/lcp_ruby/i18n_check/heuristics.rb +26 -0
  1414. data/lib/lcp_ruby/i18n_check/key_deriver.rb +136 -0
  1415. data/lib/lcp_ruby/i18n_check/offense.rb +29 -0
  1416. data/lib/lcp_ruby/i18n_check/registry_walker.rb +621 -0
  1417. data/lib/lcp_ruby/i18n_check/reporter.rb +96 -0
  1418. data/lib/lcp_ruby/i18n_check/runner.rb +46 -0
  1419. data/lib/lcp_ruby/i18n_check.rb +15 -0
  1420. data/lib/lcp_ruby/i18n_lint.rb +145 -0
  1421. data/lib/lcp_ruby/import/auto_mapper.rb +98 -0
  1422. data/lib/lcp_ruby/import/field_tree_builder.rb +178 -0
  1423. data/lib/lcp_ruby/import/file_parser.rb +223 -0
  1424. data/lib/lcp_ruby/import/import_dialog_handler.rb +410 -0
  1425. data/lib/lcp_ruby/import/import_job_handler.rb +224 -0
  1426. data/lib/lcp_ruby/import/row_processor.rb +281 -0
  1427. data/lib/lcp_ruby/import/setup.rb +277 -0
  1428. data/lib/lcp_ruby/import/value_coercer.rb +143 -0
  1429. data/lib/lcp_ruby/import.rb +14 -0
  1430. data/lib/lcp_ruby/json_item_wrapper.rb +152 -0
  1431. data/lib/lcp_ruby/kanban/board.rb +28 -0
  1432. data/lib/lcp_ruby/kanban/column.rb +28 -0
  1433. data/lib/lcp_ruby/kanban/default_provider.rb +376 -0
  1434. data/lib/lcp_ruby/kanban/host_provider.rb +94 -0
  1435. data/lib/lcp_ruby/kanban/move_result.rb +52 -0
  1436. data/lib/lcp_ruby/kanban/provider_test_harness.rb +54 -0
  1437. data/lib/lcp_ruby/kanban/swimlane.rb +21 -0
  1438. data/lib/lcp_ruby/menu.rb +46 -0
  1439. data/lib/lcp_ruby/metadata/aggregate_definition.rb +6 -0
  1440. data/lib/lcp_ruby/metadata/association_definition.rb +196 -0
  1441. data/lib/lcp_ruby/metadata/auth_validator.rb +222 -0
  1442. data/lib/lcp_ruby/metadata/configuration_validator.rb +7958 -0
  1443. data/lib/lcp_ruby/metadata/contract_result.rb +9 -0
  1444. data/lib/lcp_ruby/metadata/display_template_definition.rb +77 -0
  1445. data/lib/lcp_ruby/metadata/enum_label_resolver.rb +27 -0
  1446. data/lib/lcp_ruby/metadata/erd_generator.rb +274 -0
  1447. data/lib/lcp_ruby/metadata/event_definition.rb +55 -0
  1448. data/lib/lcp_ruby/metadata/field_definition.rb +267 -0
  1449. data/lib/lcp_ruby/metadata/group_definition.rb +31 -0
  1450. data/lib/lcp_ruby/metadata/i18n_label.rb +29 -0
  1451. data/lib/lcp_ruby/metadata/loader.rb +916 -0
  1452. data/lib/lcp_ruby/metadata/menu_definition.rb +116 -0
  1453. data/lib/lcp_ruby/metadata/menu_item.rb +792 -0
  1454. data/lib/lcp_ruby/metadata/menu_item_resolver.rb +105 -0
  1455. data/lib/lcp_ruby/metadata/model_definition.rb +612 -0
  1456. data/lib/lcp_ruby/metadata/model_hash_merger.rb +88 -0
  1457. data/lib/lcp_ruby/metadata/model_inheritance_resolver.rb +165 -0
  1458. data/lib/lcp_ruby/metadata/page_definition.rb +245 -0
  1459. data/lib/lcp_ruby/metadata/path_template.rb +231 -0
  1460. data/lib/lcp_ruby/metadata/permission_definition.rb +237 -0
  1461. data/lib/lcp_ruby/metadata/permission_merger.rb +81 -0
  1462. data/lib/lcp_ruby/metadata/presenter_definition.rb +689 -0
  1463. data/lib/lcp_ruby/metadata/reserved_names.rb +79 -0
  1464. data/lib/lcp_ruby/metadata/responsive_policy.rb +95 -0
  1465. data/lib/lcp_ruby/metadata/schema_validator.rb +172 -0
  1466. data/lib/lcp_ruby/metadata/validation_definition.rb +69 -0
  1467. data/lib/lcp_ruby/metadata/view_group_definition.rb +208 -0
  1468. data/lib/lcp_ruby/metadata/virtual_column_definition.rb +154 -0
  1469. data/lib/lcp_ruby/metadata/zone_definition.rb +423 -0
  1470. data/lib/lcp_ruby/metrics/collector.rb +123 -0
  1471. data/lib/lcp_ruby/metrics/collector_registry.rb +57 -0
  1472. data/lib/lcp_ruby/metrics/error_recorder.rb +70 -0
  1473. data/lib/lcp_ruby/metrics/fingerprint.rb +33 -0
  1474. data/lib/lcp_ruby/metrics/json_query.rb +47 -0
  1475. data/lib/lcp_ruby/metrics/metric_definitions.rb +105 -0
  1476. data/lib/lcp_ruby/metrics/prometheus_check.rb +9 -0
  1477. data/lib/lcp_ruby/metrics/rate_limiter.rb +99 -0
  1478. data/lib/lcp_ruby/metrics/setup.rb +71 -0
  1479. data/lib/lcp_ruby/metrics/subscriber.rb +126 -0
  1480. data/lib/lcp_ruby/model_factory/aggregate_applicator.rb +14 -0
  1481. data/lib/lcp_ruby/model_factory/api_association_applicator.rb +119 -0
  1482. data/lib/lcp_ruby/model_factory/api_builder.rb +85 -0
  1483. data/lib/lcp_ruby/model_factory/array_type.rb +78 -0
  1484. data/lib/lcp_ruby/model_factory/array_type_applicator.rb +33 -0
  1485. data/lib/lcp_ruby/model_factory/association_applicator.rb +201 -0
  1486. data/lib/lcp_ruby/model_factory/attachment_applicator.rb +160 -0
  1487. data/lib/lcp_ruby/model_factory/auditing_applicator.rb +72 -0
  1488. data/lib/lcp_ruby/model_factory/builder.rb +235 -0
  1489. data/lib/lcp_ruby/model_factory/callback_applicator.rb +63 -0
  1490. data/lib/lcp_ruby/model_factory/computed_applicator.rb +55 -0
  1491. data/lib/lcp_ruby/model_factory/default_applicator.rb +85 -0
  1492. data/lib/lcp_ruby/model_factory/enum_applicator.rb +24 -0
  1493. data/lib/lcp_ruby/model_factory/inherited_parent_validator_applicator.rb +39 -0
  1494. data/lib/lcp_ruby/model_factory/label_method_builder.rb +82 -0
  1495. data/lib/lcp_ruby/model_factory/managed_tracking.rb +71 -0
  1496. data/lib/lcp_ruby/model_factory/positioning_applicator.rb +23 -0
  1497. data/lib/lcp_ruby/model_factory/ransack_applicator.rb +66 -0
  1498. data/lib/lcp_ruby/model_factory/registry.rb +33 -0
  1499. data/lib/lcp_ruby/model_factory/schema_manager.rb +655 -0
  1500. data/lib/lcp_ruby/model_factory/scope_applicator.rb +87 -0
  1501. data/lib/lcp_ruby/model_factory/sequence_applicator.rb +173 -0
  1502. data/lib/lcp_ruby/model_factory/service_accessor_applicator.rb +40 -0
  1503. data/lib/lcp_ruby/model_factory/soft_delete_applicator.rb +141 -0
  1504. data/lib/lcp_ruby/model_factory/transform_applicator.rb +51 -0
  1505. data/lib/lcp_ruby/model_factory/tree_applicator.rb +239 -0
  1506. data/lib/lcp_ruby/model_factory/userstamps_applicator.rb +73 -0
  1507. data/lib/lcp_ruby/model_factory/validation_applicator.rb +319 -0
  1508. data/lib/lcp_ruby/model_factory/virtual_column_applicator.rb +79 -0
  1509. data/lib/lcp_ruby/model_factory/workflow_applicator.rb +141 -0
  1510. data/lib/lcp_ruby/pages/change_handler.rb +15 -0
  1511. data/lib/lcp_ruby/pages/contract_validator.rb +74 -0
  1512. data/lib/lcp_ruby/pages/definition_validator.rb +42 -0
  1513. data/lib/lcp_ruby/pages/filter_form.rb +200 -0
  1514. data/lib/lcp_ruby/pages/filter_form_validator.rb +636 -0
  1515. data/lib/lcp_ruby/pages/registry.rb +133 -0
  1516. data/lib/lcp_ruby/pages/resolver.rb +32 -0
  1517. data/lib/lcp_ruby/pages/scope_context_resolver.rb +37 -0
  1518. data/lib/lcp_ruby/pages/scope_filter_set.rb +57 -0
  1519. data/lib/lcp_ruby/pages/setup.rb +46 -0
  1520. data/lib/lcp_ruby/path_utils.rb +12 -0
  1521. data/lib/lcp_ruby/permissions/change_handler.rb +22 -0
  1522. data/lib/lcp_ruby/permissions/contract_validator.rb +74 -0
  1523. data/lib/lcp_ruby/permissions/definition_validator.rb +119 -0
  1524. data/lib/lcp_ruby/permissions/registry.rb +135 -0
  1525. data/lib/lcp_ruby/permissions/setup.rb +51 -0
  1526. data/lib/lcp_ruby/permissions/source_resolver.rb +56 -0
  1527. data/lib/lcp_ruby/presenter/action_set.rb +236 -0
  1528. data/lib/lcp_ruby/presenter/breadcrumb_builder.rb +183 -0
  1529. data/lib/lcp_ruby/presenter/breadcrumb_path_helper.rb +17 -0
  1530. data/lib/lcp_ruby/presenter/column_set.rb +268 -0
  1531. data/lib/lcp_ruby/presenter/enrichment.rb +136 -0
  1532. data/lib/lcp_ruby/presenter/field_value_resolver.rb +237 -0
  1533. data/lib/lcp_ruby/presenter/includes_resolver/association_dependency.rb +59 -0
  1534. data/lib/lcp_ruby/presenter/includes_resolver/dependency_collector.rb +394 -0
  1535. data/lib/lcp_ruby/presenter/includes_resolver/loading_strategy.rb +70 -0
  1536. data/lib/lcp_ruby/presenter/includes_resolver/strategy_resolver.rb +123 -0
  1537. data/lib/lcp_ruby/presenter/includes_resolver.rb +42 -0
  1538. data/lib/lcp_ruby/presenter/layout_builder.rb +467 -0
  1539. data/lib/lcp_ruby/presenter/link_resolver.rb +65 -0
  1540. data/lib/lcp_ruby/presenter/metadata_lookup.rb +28 -0
  1541. data/lib/lcp_ruby/presenter/resolver.rb +25 -0
  1542. data/lib/lcp_ruby/record_aliases/metadata_checker.rb +213 -0
  1543. data/lib/lcp_ruby/record_aliases/setup.rb +212 -0
  1544. data/lib/lcp_ruby/reserved_route_segments.rb +37 -0
  1545. data/lib/lcp_ruby/roles/change_handler.rb +11 -0
  1546. data/lib/lcp_ruby/roles/contract_validator.rb +67 -0
  1547. data/lib/lcp_ruby/roles/registry.rb +89 -0
  1548. data/lib/lcp_ruby/roles/setup.rb +50 -0
  1549. data/lib/lcp_ruby/routing/presenter_routes.rb +104 -0
  1550. data/lib/lcp_ruby/saved_filters/change_handler.rb +13 -0
  1551. data/lib/lcp_ruby/saved_filters/contract_validator.rb +85 -0
  1552. data/lib/lcp_ruby/saved_filters/registry.rb +36 -0
  1553. data/lib/lcp_ruby/saved_filters/resolver.rb +108 -0
  1554. data/lib/lcp_ruby/saved_filters/setup.rb +42 -0
  1555. data/lib/lcp_ruby/saved_filters/stale_field_validator.rb +84 -0
  1556. data/lib/lcp_ruby/schemas/auth.json +208 -0
  1557. data/lib/lcp_ruby/schemas/menu.json +338 -0
  1558. data/lib/lcp_ruby/schemas/model.json +1161 -0
  1559. data/lib/lcp_ruby/schemas/page.json +877 -0
  1560. data/lib/lcp_ruby/schemas/permission.json +454 -0
  1561. data/lib/lcp_ruby/schemas/presenter.json +2274 -0
  1562. data/lib/lcp_ruby/schemas/theme.json +62 -0
  1563. data/lib/lcp_ruby/schemas/type.json +146 -0
  1564. data/lib/lcp_ruby/schemas/view_group.json +163 -0
  1565. data/lib/lcp_ruby/search/custom_field_filter.rb +171 -0
  1566. data/lib/lcp_ruby/search/custom_filter_interceptor.rb +40 -0
  1567. data/lib/lcp_ruby/search/filter_metadata_builder.rb +409 -0
  1568. data/lib/lcp_ruby/search/filter_param_builder.rb +177 -0
  1569. data/lib/lcp_ruby/search/operator_registry.rb +79 -0
  1570. data/lib/lcp_ruby/search/param_sanitizer.rb +25 -0
  1571. data/lib/lcp_ruby/search/parameter_definition.rb +187 -0
  1572. data/lib/lcp_ruby/search/parameterized_scope_applicator.rb +129 -0
  1573. data/lib/lcp_ruby/search/query_builder.rb +143 -0
  1574. data/lib/lcp_ruby/search/query_language_parser.rb +549 -0
  1575. data/lib/lcp_ruby/search/query_language_serializer.rb +193 -0
  1576. data/lib/lcp_ruby/search/quick_search.rb +162 -0
  1577. data/lib/lcp_ruby/search/relative_date_expander.rb +57 -0
  1578. data/lib/lcp_ruby/search_result.rb +70 -0
  1579. data/lib/lcp_ruby/sequences/sequence_manager.rb +51 -0
  1580. data/lib/lcp_ruby/services/accessors/json_field.rb +23 -0
  1581. data/lib/lcp_ruby/services/built_in_accessors.rb +17 -0
  1582. data/lib/lcp_ruby/services/built_in_defaults.rb +22 -0
  1583. data/lib/lcp_ruby/services/built_in_transforms.rb +20 -0
  1584. data/lib/lcp_ruby/services/checker.rb +133 -0
  1585. data/lib/lcp_ruby/services/registry.rb +83 -0
  1586. data/lib/lcp_ruby/skills_installer.rb +73 -0
  1587. data/lib/lcp_ruby/sort/enum_sort_order.rb +38 -0
  1588. data/lib/lcp_ruby/tasks/destroy_order_resolver.rb +57 -0
  1589. data/lib/lcp_ruby/tasks/doctor.rb +294 -0
  1590. data/lib/lcp_ruby/tasks/permission_resolve_formatter.rb +245 -0
  1591. data/lib/lcp_ruby/types/built_in_types.rb +157 -0
  1592. data/lib/lcp_ruby/types/transforms/base_transform.rb +11 -0
  1593. data/lib/lcp_ruby/types/transforms/downcase.rb +11 -0
  1594. data/lib/lcp_ruby/types/transforms/normalize_phone.rb +19 -0
  1595. data/lib/lcp_ruby/types/transforms/normalize_url.rb +16 -0
  1596. data/lib/lcp_ruby/types/transforms/strip.rb +11 -0
  1597. data/lib/lcp_ruby/types/type_definition.rb +112 -0
  1598. data/lib/lcp_ruby/types/type_registry.rb +75 -0
  1599. data/lib/lcp_ruby/url_safety.rb +97 -0
  1600. data/lib/lcp_ruby/user_snapshot.rb +15 -0
  1601. data/lib/lcp_ruby/version.rb +3 -0
  1602. data/lib/lcp_ruby/view_slots/registry.rb +71 -0
  1603. data/lib/lcp_ruby/view_slots/slot_component.rb +22 -0
  1604. data/lib/lcp_ruby/view_slots/slot_context.rb +20 -0
  1605. data/lib/lcp_ruby/virtual_columns/builder.rb +234 -0
  1606. data/lib/lcp_ruby/virtual_columns/collector.rb +186 -0
  1607. data/lib/lcp_ruby/virtual_columns.rb +4 -0
  1608. data/lib/lcp_ruby/virtual_fields/synthetic_marker.rb +17 -0
  1609. data/lib/lcp_ruby/virtual_fields/types/array_of.rb +49 -0
  1610. data/lib/lcp_ruby/virtual_fields/virtual_field.rb +107 -0
  1611. data/lib/lcp_ruby/virtual_fields/virtual_form.rb +144 -0
  1612. data/lib/lcp_ruby/widgets/chart_palette.rb +25 -0
  1613. data/lib/lcp_ruby/widgets/chartkick_check.rb +9 -0
  1614. data/lib/lcp_ruby/widgets/data_resolver.rb +676 -0
  1615. data/lib/lcp_ruby/widgets/date_grouper.rb +54 -0
  1616. data/lib/lcp_ruby/widgets/presenter_zone_resolver.rb +170 -0
  1617. data/lib/lcp_ruby/widgets/record_source_resolver.rb +56 -0
  1618. data/lib/lcp_ruby/widgets/scope_applicator.rb +187 -0
  1619. data/lib/lcp_ruby/workflow/approval/activation_handler.rb +39 -0
  1620. data/lib/lcp_ruby/workflow/approval/approval_definition.rb +117 -0
  1621. data/lib/lcp_ruby/workflow/approval/approver_resolver.rb +98 -0
  1622. data/lib/lcp_ruby/workflow/approval/cleanup_handler.rb +37 -0
  1623. data/lib/lcp_ruby/workflow/approval/contract_validator.rb +96 -0
  1624. data/lib/lcp_ruby/workflow/approval/data_builder.rb +53 -0
  1625. data/lib/lcp_ruby/workflow/approval/discard_handler.rb +51 -0
  1626. data/lib/lcp_ruby/workflow/approval/engine.rb +314 -0
  1627. data/lib/lcp_ruby/workflow/approval/registry.rb +40 -0
  1628. data/lib/lcp_ruby/workflow/approval/resolution_handler.rb +103 -0
  1629. data/lib/lcp_ruby/workflow/approval/setup.rb +138 -0
  1630. data/lib/lcp_ruby/workflow/approval/step_definition.rb +52 -0
  1631. data/lib/lcp_ruby/workflow/approval/step_evaluator.rb +163 -0
  1632. data/lib/lcp_ruby/workflow/approval/system_evaluator.rb +29 -0
  1633. data/lib/lcp_ruby/workflow/approval/task_manager.rb +202 -0
  1634. data/lib/lcp_ruby/workflow/audit_contract_validator.rb +64 -0
  1635. data/lib/lcp_ruby/workflow/audit_registry.rb +24 -0
  1636. data/lib/lcp_ruby/workflow/audit_writer.rb +51 -0
  1637. data/lib/lcp_ruby/workflow/change_handler.rb +14 -0
  1638. data/lib/lcp_ruby/workflow/contract.rb +21 -0
  1639. data/lib/lcp_ruby/workflow/contract_validator.rb +44 -0
  1640. data/lib/lcp_ruby/workflow/errors.rb +12 -0
  1641. data/lib/lcp_ruby/workflow/host_source.rb +19 -0
  1642. data/lib/lcp_ruby/workflow/mermaid_builder.rb +217 -0
  1643. data/lib/lcp_ruby/workflow/model_source.rb +79 -0
  1644. data/lib/lcp_ruby/workflow/registry.rb +113 -0
  1645. data/lib/lcp_ruby/workflow/resolver.rb +32 -0
  1646. data/lib/lcp_ruby/workflow/setup.rb +135 -0
  1647. data/lib/lcp_ruby/workflow/state_definition.rb +59 -0
  1648. data/lib/lcp_ruby/workflow/state_machine.rb +78 -0
  1649. data/lib/lcp_ruby/workflow/static_source.rb +20 -0
  1650. data/lib/lcp_ruby/workflow/transition_action_builder.rb +46 -0
  1651. data/lib/lcp_ruby/workflow/transition_definition.rb +70 -0
  1652. data/lib/lcp_ruby/workflow/transition_executor.rb +140 -0
  1653. data/lib/lcp_ruby/workflow/transition_label_resolver.rb +21 -0
  1654. data/lib/lcp_ruby/workflow/transition_result.rb +20 -0
  1655. data/lib/lcp_ruby/workflow/value_resolver.rb +58 -0
  1656. data/lib/lcp_ruby/workflow/workflow_definition.rb +195 -0
  1657. data/lib/lcp_ruby.rb +764 -0
  1658. data/lib/rubocop/cop/lcp_ruby/no_hardcoded_i18n_string.rb +249 -0
  1659. data/lib/tasks/lcp_ruby.rake +432 -0
  1660. data/lib/tasks/lcp_ruby_assets.rake +37 -0
  1661. data/lib/tasks/lcp_ruby_auth.rake +49 -0
  1662. data/lib/tasks/lcp_ruby_db.rake +76 -0
  1663. data/lib/tasks/lcp_ruby_doctor.rake +20 -0
  1664. data/lib/tasks/lcp_ruby_feature_catalog.rake +61 -0
  1665. data/lib/tasks/lcp_ruby_gapfree_sequences.rake +39 -0
  1666. data/lib/tasks/lcp_ruby_i18n_check.rake +23 -0
  1667. data/lib/tasks/lcp_ruby_i18n_lint.rake +20 -0
  1668. data/lib/tasks/lcp_ruby_invariant_check.rake +72 -0
  1669. data/vendor/assets/javascripts/lcp_ruby/activestorage.min.js +866 -0
  1670. data/vendor/assets/javascripts/lcp_ruby/highlight.min.js +1244 -0
  1671. data/vendor/assets/javascripts/lcp_ruby/lucide.min.js +12 -0
  1672. data/vendor/assets/javascripts/lcp_ruby/stimulus.umd.js +2588 -0
  1673. data/vendor/assets/javascripts/lcp_ruby/tom-select.complete.min.js +444 -0
  1674. data/vendor/assets/stylesheets/lcp_ruby/highlight-github.min.css +12 -0
  1675. data/vendor/assets/stylesheets/lcp_ruby/tom-select.css +412 -0
  1676. metadata +1950 -0
@@ -0,0 +1,2588 @@
1
+ /*
2
+ Stimulus 3.2.1
3
+ Copyright © 2023 Basecamp, LLC
4
+ */
5
+ (function (global, factory) {
6
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
7
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
8
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Stimulus = {}));
9
+ }(this, (function (exports) { 'use strict';
10
+
11
+ class EventListener {
12
+ constructor(eventTarget, eventName, eventOptions) {
13
+ this.eventTarget = eventTarget;
14
+ this.eventName = eventName;
15
+ this.eventOptions = eventOptions;
16
+ this.unorderedBindings = new Set();
17
+ }
18
+ connect() {
19
+ this.eventTarget.addEventListener(this.eventName, this, this.eventOptions);
20
+ }
21
+ disconnect() {
22
+ this.eventTarget.removeEventListener(this.eventName, this, this.eventOptions);
23
+ }
24
+ bindingConnected(binding) {
25
+ this.unorderedBindings.add(binding);
26
+ }
27
+ bindingDisconnected(binding) {
28
+ this.unorderedBindings.delete(binding);
29
+ }
30
+ handleEvent(event) {
31
+ const extendedEvent = extendEvent(event);
32
+ for (const binding of this.bindings) {
33
+ if (extendedEvent.immediatePropagationStopped) {
34
+ break;
35
+ }
36
+ else {
37
+ binding.handleEvent(extendedEvent);
38
+ }
39
+ }
40
+ }
41
+ hasBindings() {
42
+ return this.unorderedBindings.size > 0;
43
+ }
44
+ get bindings() {
45
+ return Array.from(this.unorderedBindings).sort((left, right) => {
46
+ const leftIndex = left.index, rightIndex = right.index;
47
+ return leftIndex < rightIndex ? -1 : leftIndex > rightIndex ? 1 : 0;
48
+ });
49
+ }
50
+ }
51
+ function extendEvent(event) {
52
+ if ("immediatePropagationStopped" in event) {
53
+ return event;
54
+ }
55
+ else {
56
+ const { stopImmediatePropagation } = event;
57
+ return Object.assign(event, {
58
+ immediatePropagationStopped: false,
59
+ stopImmediatePropagation() {
60
+ this.immediatePropagationStopped = true;
61
+ stopImmediatePropagation.call(this);
62
+ },
63
+ });
64
+ }
65
+ }
66
+
67
+ class Dispatcher {
68
+ constructor(application) {
69
+ this.application = application;
70
+ this.eventListenerMaps = new Map();
71
+ this.started = false;
72
+ }
73
+ start() {
74
+ if (!this.started) {
75
+ this.started = true;
76
+ this.eventListeners.forEach((eventListener) => eventListener.connect());
77
+ }
78
+ }
79
+ stop() {
80
+ if (this.started) {
81
+ this.started = false;
82
+ this.eventListeners.forEach((eventListener) => eventListener.disconnect());
83
+ }
84
+ }
85
+ get eventListeners() {
86
+ return Array.from(this.eventListenerMaps.values()).reduce((listeners, map) => listeners.concat(Array.from(map.values())), []);
87
+ }
88
+ bindingConnected(binding) {
89
+ this.fetchEventListenerForBinding(binding).bindingConnected(binding);
90
+ }
91
+ bindingDisconnected(binding, clearEventListeners = false) {
92
+ this.fetchEventListenerForBinding(binding).bindingDisconnected(binding);
93
+ if (clearEventListeners)
94
+ this.clearEventListenersForBinding(binding);
95
+ }
96
+ handleError(error, message, detail = {}) {
97
+ this.application.handleError(error, `Error ${message}`, detail);
98
+ }
99
+ clearEventListenersForBinding(binding) {
100
+ const eventListener = this.fetchEventListenerForBinding(binding);
101
+ if (!eventListener.hasBindings()) {
102
+ eventListener.disconnect();
103
+ this.removeMappedEventListenerFor(binding);
104
+ }
105
+ }
106
+ removeMappedEventListenerFor(binding) {
107
+ const { eventTarget, eventName, eventOptions } = binding;
108
+ const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget);
109
+ const cacheKey = this.cacheKey(eventName, eventOptions);
110
+ eventListenerMap.delete(cacheKey);
111
+ if (eventListenerMap.size == 0)
112
+ this.eventListenerMaps.delete(eventTarget);
113
+ }
114
+ fetchEventListenerForBinding(binding) {
115
+ const { eventTarget, eventName, eventOptions } = binding;
116
+ return this.fetchEventListener(eventTarget, eventName, eventOptions);
117
+ }
118
+ fetchEventListener(eventTarget, eventName, eventOptions) {
119
+ const eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget);
120
+ const cacheKey = this.cacheKey(eventName, eventOptions);
121
+ let eventListener = eventListenerMap.get(cacheKey);
122
+ if (!eventListener) {
123
+ eventListener = this.createEventListener(eventTarget, eventName, eventOptions);
124
+ eventListenerMap.set(cacheKey, eventListener);
125
+ }
126
+ return eventListener;
127
+ }
128
+ createEventListener(eventTarget, eventName, eventOptions) {
129
+ const eventListener = new EventListener(eventTarget, eventName, eventOptions);
130
+ if (this.started) {
131
+ eventListener.connect();
132
+ }
133
+ return eventListener;
134
+ }
135
+ fetchEventListenerMapForEventTarget(eventTarget) {
136
+ let eventListenerMap = this.eventListenerMaps.get(eventTarget);
137
+ if (!eventListenerMap) {
138
+ eventListenerMap = new Map();
139
+ this.eventListenerMaps.set(eventTarget, eventListenerMap);
140
+ }
141
+ return eventListenerMap;
142
+ }
143
+ cacheKey(eventName, eventOptions) {
144
+ const parts = [eventName];
145
+ Object.keys(eventOptions)
146
+ .sort()
147
+ .forEach((key) => {
148
+ parts.push(`${eventOptions[key] ? "" : "!"}${key}`);
149
+ });
150
+ return parts.join(":");
151
+ }
152
+ }
153
+
154
+ const defaultActionDescriptorFilters = {
155
+ stop({ event, value }) {
156
+ if (value)
157
+ event.stopPropagation();
158
+ return true;
159
+ },
160
+ prevent({ event, value }) {
161
+ if (value)
162
+ event.preventDefault();
163
+ return true;
164
+ },
165
+ self({ event, value, element }) {
166
+ if (value) {
167
+ return element === event.target;
168
+ }
169
+ else {
170
+ return true;
171
+ }
172
+ },
173
+ };
174
+ const descriptorPattern = /^(?:(?:([^.]+?)\+)?(.+?)(?:\.(.+?))?(?:@(window|document))?->)?(.+?)(?:#([^:]+?))(?::(.+))?$/;
175
+ function parseActionDescriptorString(descriptorString) {
176
+ const source = descriptorString.trim();
177
+ const matches = source.match(descriptorPattern) || [];
178
+ let eventName = matches[2];
179
+ let keyFilter = matches[3];
180
+ if (keyFilter && !["keydown", "keyup", "keypress"].includes(eventName)) {
181
+ eventName += `.${keyFilter}`;
182
+ keyFilter = "";
183
+ }
184
+ return {
185
+ eventTarget: parseEventTarget(matches[4]),
186
+ eventName,
187
+ eventOptions: matches[7] ? parseEventOptions(matches[7]) : {},
188
+ identifier: matches[5],
189
+ methodName: matches[6],
190
+ keyFilter: matches[1] || keyFilter,
191
+ };
192
+ }
193
+ function parseEventTarget(eventTargetName) {
194
+ if (eventTargetName == "window") {
195
+ return window;
196
+ }
197
+ else if (eventTargetName == "document") {
198
+ return document;
199
+ }
200
+ }
201
+ function parseEventOptions(eventOptions) {
202
+ return eventOptions
203
+ .split(":")
204
+ .reduce((options, token) => Object.assign(options, { [token.replace(/^!/, "")]: !/^!/.test(token) }), {});
205
+ }
206
+ function stringifyEventTarget(eventTarget) {
207
+ if (eventTarget == window) {
208
+ return "window";
209
+ }
210
+ else if (eventTarget == document) {
211
+ return "document";
212
+ }
213
+ }
214
+
215
+ function camelize(value) {
216
+ return value.replace(/(?:[_-])([a-z0-9])/g, (_, char) => char.toUpperCase());
217
+ }
218
+ function namespaceCamelize(value) {
219
+ return camelize(value.replace(/--/g, "-").replace(/__/g, "_"));
220
+ }
221
+ function capitalize(value) {
222
+ return value.charAt(0).toUpperCase() + value.slice(1);
223
+ }
224
+ function dasherize(value) {
225
+ return value.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`);
226
+ }
227
+ function tokenize(value) {
228
+ return value.match(/[^\s]+/g) || [];
229
+ }
230
+
231
+ function isSomething(object) {
232
+ return object !== null && object !== undefined;
233
+ }
234
+ function hasProperty(object, property) {
235
+ return Object.prototype.hasOwnProperty.call(object, property);
236
+ }
237
+
238
+ const allModifiers = ["meta", "ctrl", "alt", "shift"];
239
+ class Action {
240
+ constructor(element, index, descriptor, schema) {
241
+ this.element = element;
242
+ this.index = index;
243
+ this.eventTarget = descriptor.eventTarget || element;
244
+ this.eventName = descriptor.eventName || getDefaultEventNameForElement(element) || error("missing event name");
245
+ this.eventOptions = descriptor.eventOptions || {};
246
+ this.identifier = descriptor.identifier || error("missing identifier");
247
+ this.methodName = descriptor.methodName || error("missing method name");
248
+ this.keyFilter = descriptor.keyFilter || "";
249
+ this.schema = schema;
250
+ }
251
+ static forToken(token, schema) {
252
+ return new this(token.element, token.index, parseActionDescriptorString(token.content), schema);
253
+ }
254
+ toString() {
255
+ const eventFilter = this.keyFilter ? `.${this.keyFilter}` : "";
256
+ const eventTarget = this.eventTargetName ? `@${this.eventTargetName}` : "";
257
+ return `${this.eventName}${eventFilter}${eventTarget}->${this.identifier}#${this.methodName}`;
258
+ }
259
+ shouldIgnoreKeyboardEvent(event) {
260
+ if (!this.keyFilter) {
261
+ return false;
262
+ }
263
+ const filters = this.keyFilter.split("+");
264
+ if (this.keyFilterDissatisfied(event, filters)) {
265
+ return true;
266
+ }
267
+ const standardFilter = filters.filter((key) => !allModifiers.includes(key))[0];
268
+ if (!standardFilter) {
269
+ return false;
270
+ }
271
+ if (!hasProperty(this.keyMappings, standardFilter)) {
272
+ error(`contains unknown key filter: ${this.keyFilter}`);
273
+ }
274
+ return this.keyMappings[standardFilter].toLowerCase() !== event.key.toLowerCase();
275
+ }
276
+ shouldIgnoreMouseEvent(event) {
277
+ if (!this.keyFilter) {
278
+ return false;
279
+ }
280
+ const filters = [this.keyFilter];
281
+ if (this.keyFilterDissatisfied(event, filters)) {
282
+ return true;
283
+ }
284
+ return false;
285
+ }
286
+ get params() {
287
+ const params = {};
288
+ const pattern = new RegExp(`^data-${this.identifier}-(.+)-param$`, "i");
289
+ for (const { name, value } of Array.from(this.element.attributes)) {
290
+ const match = name.match(pattern);
291
+ const key = match && match[1];
292
+ if (key) {
293
+ params[camelize(key)] = typecast(value);
294
+ }
295
+ }
296
+ return params;
297
+ }
298
+ get eventTargetName() {
299
+ return stringifyEventTarget(this.eventTarget);
300
+ }
301
+ get keyMappings() {
302
+ return this.schema.keyMappings;
303
+ }
304
+ keyFilterDissatisfied(event, filters) {
305
+ const [meta, ctrl, alt, shift] = allModifiers.map((modifier) => filters.includes(modifier));
306
+ return event.metaKey !== meta || event.ctrlKey !== ctrl || event.altKey !== alt || event.shiftKey !== shift;
307
+ }
308
+ }
309
+ const defaultEventNames = {
310
+ a: () => "click",
311
+ button: () => "click",
312
+ form: () => "submit",
313
+ details: () => "toggle",
314
+ input: (e) => (e.getAttribute("type") == "submit" ? "click" : "input"),
315
+ select: () => "change",
316
+ textarea: () => "input",
317
+ };
318
+ function getDefaultEventNameForElement(element) {
319
+ const tagName = element.tagName.toLowerCase();
320
+ if (tagName in defaultEventNames) {
321
+ return defaultEventNames[tagName](element);
322
+ }
323
+ }
324
+ function error(message) {
325
+ throw new Error(message);
326
+ }
327
+ function typecast(value) {
328
+ try {
329
+ return JSON.parse(value);
330
+ }
331
+ catch (o_O) {
332
+ return value;
333
+ }
334
+ }
335
+
336
+ class Binding {
337
+ constructor(context, action) {
338
+ this.context = context;
339
+ this.action = action;
340
+ }
341
+ get index() {
342
+ return this.action.index;
343
+ }
344
+ get eventTarget() {
345
+ return this.action.eventTarget;
346
+ }
347
+ get eventOptions() {
348
+ return this.action.eventOptions;
349
+ }
350
+ get identifier() {
351
+ return this.context.identifier;
352
+ }
353
+ handleEvent(event) {
354
+ const actionEvent = this.prepareActionEvent(event);
355
+ if (this.willBeInvokedByEvent(event) && this.applyEventModifiers(actionEvent)) {
356
+ this.invokeWithEvent(actionEvent);
357
+ }
358
+ }
359
+ get eventName() {
360
+ return this.action.eventName;
361
+ }
362
+ get method() {
363
+ const method = this.controller[this.methodName];
364
+ if (typeof method == "function") {
365
+ return method;
366
+ }
367
+ throw new Error(`Action "${this.action}" references undefined method "${this.methodName}"`);
368
+ }
369
+ applyEventModifiers(event) {
370
+ const { element } = this.action;
371
+ const { actionDescriptorFilters } = this.context.application;
372
+ const { controller } = this.context;
373
+ let passes = true;
374
+ for (const [name, value] of Object.entries(this.eventOptions)) {
375
+ if (name in actionDescriptorFilters) {
376
+ const filter = actionDescriptorFilters[name];
377
+ passes = passes && filter({ name, value, event, element, controller });
378
+ }
379
+ else {
380
+ continue;
381
+ }
382
+ }
383
+ return passes;
384
+ }
385
+ prepareActionEvent(event) {
386
+ return Object.assign(event, { params: this.action.params });
387
+ }
388
+ invokeWithEvent(event) {
389
+ const { target, currentTarget } = event;
390
+ try {
391
+ this.method.call(this.controller, event);
392
+ this.context.logDebugActivity(this.methodName, { event, target, currentTarget, action: this.methodName });
393
+ }
394
+ catch (error) {
395
+ const { identifier, controller, element, index } = this;
396
+ const detail = { identifier, controller, element, index, event };
397
+ this.context.handleError(error, `invoking action "${this.action}"`, detail);
398
+ }
399
+ }
400
+ willBeInvokedByEvent(event) {
401
+ const eventTarget = event.target;
402
+ if (event instanceof KeyboardEvent && this.action.shouldIgnoreKeyboardEvent(event)) {
403
+ return false;
404
+ }
405
+ if (event instanceof MouseEvent && this.action.shouldIgnoreMouseEvent(event)) {
406
+ return false;
407
+ }
408
+ if (this.element === eventTarget) {
409
+ return true;
410
+ }
411
+ else if (eventTarget instanceof Element && this.element.contains(eventTarget)) {
412
+ return this.scope.containsElement(eventTarget);
413
+ }
414
+ else {
415
+ return this.scope.containsElement(this.action.element);
416
+ }
417
+ }
418
+ get controller() {
419
+ return this.context.controller;
420
+ }
421
+ get methodName() {
422
+ return this.action.methodName;
423
+ }
424
+ get element() {
425
+ return this.scope.element;
426
+ }
427
+ get scope() {
428
+ return this.context.scope;
429
+ }
430
+ }
431
+
432
+ class ElementObserver {
433
+ constructor(element, delegate) {
434
+ this.mutationObserverInit = { attributes: true, childList: true, subtree: true };
435
+ this.element = element;
436
+ this.started = false;
437
+ this.delegate = delegate;
438
+ this.elements = new Set();
439
+ this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations));
440
+ }
441
+ start() {
442
+ if (!this.started) {
443
+ this.started = true;
444
+ this.mutationObserver.observe(this.element, this.mutationObserverInit);
445
+ this.refresh();
446
+ }
447
+ }
448
+ pause(callback) {
449
+ if (this.started) {
450
+ this.mutationObserver.disconnect();
451
+ this.started = false;
452
+ }
453
+ callback();
454
+ if (!this.started) {
455
+ this.mutationObserver.observe(this.element, this.mutationObserverInit);
456
+ this.started = true;
457
+ }
458
+ }
459
+ stop() {
460
+ if (this.started) {
461
+ this.mutationObserver.takeRecords();
462
+ this.mutationObserver.disconnect();
463
+ this.started = false;
464
+ }
465
+ }
466
+ refresh() {
467
+ if (this.started) {
468
+ const matches = new Set(this.matchElementsInTree());
469
+ for (const element of Array.from(this.elements)) {
470
+ if (!matches.has(element)) {
471
+ this.removeElement(element);
472
+ }
473
+ }
474
+ for (const element of Array.from(matches)) {
475
+ this.addElement(element);
476
+ }
477
+ }
478
+ }
479
+ processMutations(mutations) {
480
+ if (this.started) {
481
+ for (const mutation of mutations) {
482
+ this.processMutation(mutation);
483
+ }
484
+ }
485
+ }
486
+ processMutation(mutation) {
487
+ if (mutation.type == "attributes") {
488
+ this.processAttributeChange(mutation.target, mutation.attributeName);
489
+ }
490
+ else if (mutation.type == "childList") {
491
+ this.processRemovedNodes(mutation.removedNodes);
492
+ this.processAddedNodes(mutation.addedNodes);
493
+ }
494
+ }
495
+ processAttributeChange(element, attributeName) {
496
+ if (this.elements.has(element)) {
497
+ if (this.delegate.elementAttributeChanged && this.matchElement(element)) {
498
+ this.delegate.elementAttributeChanged(element, attributeName);
499
+ }
500
+ else {
501
+ this.removeElement(element);
502
+ }
503
+ }
504
+ else if (this.matchElement(element)) {
505
+ this.addElement(element);
506
+ }
507
+ }
508
+ processRemovedNodes(nodes) {
509
+ for (const node of Array.from(nodes)) {
510
+ const element = this.elementFromNode(node);
511
+ if (element) {
512
+ this.processTree(element, this.removeElement);
513
+ }
514
+ }
515
+ }
516
+ processAddedNodes(nodes) {
517
+ for (const node of Array.from(nodes)) {
518
+ const element = this.elementFromNode(node);
519
+ if (element && this.elementIsActive(element)) {
520
+ this.processTree(element, this.addElement);
521
+ }
522
+ }
523
+ }
524
+ matchElement(element) {
525
+ return this.delegate.matchElement(element);
526
+ }
527
+ matchElementsInTree(tree = this.element) {
528
+ return this.delegate.matchElementsInTree(tree);
529
+ }
530
+ processTree(tree, processor) {
531
+ for (const element of this.matchElementsInTree(tree)) {
532
+ processor.call(this, element);
533
+ }
534
+ }
535
+ elementFromNode(node) {
536
+ if (node.nodeType == Node.ELEMENT_NODE) {
537
+ return node;
538
+ }
539
+ }
540
+ elementIsActive(element) {
541
+ if (element.isConnected != this.element.isConnected) {
542
+ return false;
543
+ }
544
+ else {
545
+ return this.element.contains(element);
546
+ }
547
+ }
548
+ addElement(element) {
549
+ if (!this.elements.has(element)) {
550
+ if (this.elementIsActive(element)) {
551
+ this.elements.add(element);
552
+ if (this.delegate.elementMatched) {
553
+ this.delegate.elementMatched(element);
554
+ }
555
+ }
556
+ }
557
+ }
558
+ removeElement(element) {
559
+ if (this.elements.has(element)) {
560
+ this.elements.delete(element);
561
+ if (this.delegate.elementUnmatched) {
562
+ this.delegate.elementUnmatched(element);
563
+ }
564
+ }
565
+ }
566
+ }
567
+
568
+ class AttributeObserver {
569
+ constructor(element, attributeName, delegate) {
570
+ this.attributeName = attributeName;
571
+ this.delegate = delegate;
572
+ this.elementObserver = new ElementObserver(element, this);
573
+ }
574
+ get element() {
575
+ return this.elementObserver.element;
576
+ }
577
+ get selector() {
578
+ return `[${this.attributeName}]`;
579
+ }
580
+ start() {
581
+ this.elementObserver.start();
582
+ }
583
+ pause(callback) {
584
+ this.elementObserver.pause(callback);
585
+ }
586
+ stop() {
587
+ this.elementObserver.stop();
588
+ }
589
+ refresh() {
590
+ this.elementObserver.refresh();
591
+ }
592
+ get started() {
593
+ return this.elementObserver.started;
594
+ }
595
+ matchElement(element) {
596
+ return element.hasAttribute(this.attributeName);
597
+ }
598
+ matchElementsInTree(tree) {
599
+ const match = this.matchElement(tree) ? [tree] : [];
600
+ const matches = Array.from(tree.querySelectorAll(this.selector));
601
+ return match.concat(matches);
602
+ }
603
+ elementMatched(element) {
604
+ if (this.delegate.elementMatchedAttribute) {
605
+ this.delegate.elementMatchedAttribute(element, this.attributeName);
606
+ }
607
+ }
608
+ elementUnmatched(element) {
609
+ if (this.delegate.elementUnmatchedAttribute) {
610
+ this.delegate.elementUnmatchedAttribute(element, this.attributeName);
611
+ }
612
+ }
613
+ elementAttributeChanged(element, attributeName) {
614
+ if (this.delegate.elementAttributeValueChanged && this.attributeName == attributeName) {
615
+ this.delegate.elementAttributeValueChanged(element, attributeName);
616
+ }
617
+ }
618
+ }
619
+
620
+ function add(map, key, value) {
621
+ fetch(map, key).add(value);
622
+ }
623
+ function del(map, key, value) {
624
+ fetch(map, key).delete(value);
625
+ prune(map, key);
626
+ }
627
+ function fetch(map, key) {
628
+ let values = map.get(key);
629
+ if (!values) {
630
+ values = new Set();
631
+ map.set(key, values);
632
+ }
633
+ return values;
634
+ }
635
+ function prune(map, key) {
636
+ const values = map.get(key);
637
+ if (values != null && values.size == 0) {
638
+ map.delete(key);
639
+ }
640
+ }
641
+
642
+ class Multimap {
643
+ constructor() {
644
+ this.valuesByKey = new Map();
645
+ }
646
+ get keys() {
647
+ return Array.from(this.valuesByKey.keys());
648
+ }
649
+ get values() {
650
+ const sets = Array.from(this.valuesByKey.values());
651
+ return sets.reduce((values, set) => values.concat(Array.from(set)), []);
652
+ }
653
+ get size() {
654
+ const sets = Array.from(this.valuesByKey.values());
655
+ return sets.reduce((size, set) => size + set.size, 0);
656
+ }
657
+ add(key, value) {
658
+ add(this.valuesByKey, key, value);
659
+ }
660
+ delete(key, value) {
661
+ del(this.valuesByKey, key, value);
662
+ }
663
+ has(key, value) {
664
+ const values = this.valuesByKey.get(key);
665
+ return values != null && values.has(value);
666
+ }
667
+ hasKey(key) {
668
+ return this.valuesByKey.has(key);
669
+ }
670
+ hasValue(value) {
671
+ const sets = Array.from(this.valuesByKey.values());
672
+ return sets.some((set) => set.has(value));
673
+ }
674
+ getValuesForKey(key) {
675
+ const values = this.valuesByKey.get(key);
676
+ return values ? Array.from(values) : [];
677
+ }
678
+ getKeysForValue(value) {
679
+ return Array.from(this.valuesByKey)
680
+ .filter(([_key, values]) => values.has(value))
681
+ .map(([key, _values]) => key);
682
+ }
683
+ }
684
+
685
+ class IndexedMultimap extends Multimap {
686
+ constructor() {
687
+ super();
688
+ this.keysByValue = new Map();
689
+ }
690
+ get values() {
691
+ return Array.from(this.keysByValue.keys());
692
+ }
693
+ add(key, value) {
694
+ super.add(key, value);
695
+ add(this.keysByValue, value, key);
696
+ }
697
+ delete(key, value) {
698
+ super.delete(key, value);
699
+ del(this.keysByValue, value, key);
700
+ }
701
+ hasValue(value) {
702
+ return this.keysByValue.has(value);
703
+ }
704
+ getKeysForValue(value) {
705
+ const set = this.keysByValue.get(value);
706
+ return set ? Array.from(set) : [];
707
+ }
708
+ }
709
+
710
+ class SelectorObserver {
711
+ constructor(element, selector, delegate, details) {
712
+ this._selector = selector;
713
+ this.details = details;
714
+ this.elementObserver = new ElementObserver(element, this);
715
+ this.delegate = delegate;
716
+ this.matchesByElement = new Multimap();
717
+ }
718
+ get started() {
719
+ return this.elementObserver.started;
720
+ }
721
+ get selector() {
722
+ return this._selector;
723
+ }
724
+ set selector(selector) {
725
+ this._selector = selector;
726
+ this.refresh();
727
+ }
728
+ start() {
729
+ this.elementObserver.start();
730
+ }
731
+ pause(callback) {
732
+ this.elementObserver.pause(callback);
733
+ }
734
+ stop() {
735
+ this.elementObserver.stop();
736
+ }
737
+ refresh() {
738
+ this.elementObserver.refresh();
739
+ }
740
+ get element() {
741
+ return this.elementObserver.element;
742
+ }
743
+ matchElement(element) {
744
+ const { selector } = this;
745
+ if (selector) {
746
+ const matches = element.matches(selector);
747
+ if (this.delegate.selectorMatchElement) {
748
+ return matches && this.delegate.selectorMatchElement(element, this.details);
749
+ }
750
+ return matches;
751
+ }
752
+ else {
753
+ return false;
754
+ }
755
+ }
756
+ matchElementsInTree(tree) {
757
+ const { selector } = this;
758
+ if (selector) {
759
+ const match = this.matchElement(tree) ? [tree] : [];
760
+ const matches = Array.from(tree.querySelectorAll(selector)).filter((match) => this.matchElement(match));
761
+ return match.concat(matches);
762
+ }
763
+ else {
764
+ return [];
765
+ }
766
+ }
767
+ elementMatched(element) {
768
+ const { selector } = this;
769
+ if (selector) {
770
+ this.selectorMatched(element, selector);
771
+ }
772
+ }
773
+ elementUnmatched(element) {
774
+ const selectors = this.matchesByElement.getKeysForValue(element);
775
+ for (const selector of selectors) {
776
+ this.selectorUnmatched(element, selector);
777
+ }
778
+ }
779
+ elementAttributeChanged(element, _attributeName) {
780
+ const { selector } = this;
781
+ if (selector) {
782
+ const matches = this.matchElement(element);
783
+ const matchedBefore = this.matchesByElement.has(selector, element);
784
+ if (matches && !matchedBefore) {
785
+ this.selectorMatched(element, selector);
786
+ }
787
+ else if (!matches && matchedBefore) {
788
+ this.selectorUnmatched(element, selector);
789
+ }
790
+ }
791
+ }
792
+ selectorMatched(element, selector) {
793
+ this.delegate.selectorMatched(element, selector, this.details);
794
+ this.matchesByElement.add(selector, element);
795
+ }
796
+ selectorUnmatched(element, selector) {
797
+ this.delegate.selectorUnmatched(element, selector, this.details);
798
+ this.matchesByElement.delete(selector, element);
799
+ }
800
+ }
801
+
802
+ class StringMapObserver {
803
+ constructor(element, delegate) {
804
+ this.element = element;
805
+ this.delegate = delegate;
806
+ this.started = false;
807
+ this.stringMap = new Map();
808
+ this.mutationObserver = new MutationObserver((mutations) => this.processMutations(mutations));
809
+ }
810
+ start() {
811
+ if (!this.started) {
812
+ this.started = true;
813
+ this.mutationObserver.observe(this.element, { attributes: true, attributeOldValue: true });
814
+ this.refresh();
815
+ }
816
+ }
817
+ stop() {
818
+ if (this.started) {
819
+ this.mutationObserver.takeRecords();
820
+ this.mutationObserver.disconnect();
821
+ this.started = false;
822
+ }
823
+ }
824
+ refresh() {
825
+ if (this.started) {
826
+ for (const attributeName of this.knownAttributeNames) {
827
+ this.refreshAttribute(attributeName, null);
828
+ }
829
+ }
830
+ }
831
+ processMutations(mutations) {
832
+ if (this.started) {
833
+ for (const mutation of mutations) {
834
+ this.processMutation(mutation);
835
+ }
836
+ }
837
+ }
838
+ processMutation(mutation) {
839
+ const attributeName = mutation.attributeName;
840
+ if (attributeName) {
841
+ this.refreshAttribute(attributeName, mutation.oldValue);
842
+ }
843
+ }
844
+ refreshAttribute(attributeName, oldValue) {
845
+ const key = this.delegate.getStringMapKeyForAttribute(attributeName);
846
+ if (key != null) {
847
+ if (!this.stringMap.has(attributeName)) {
848
+ this.stringMapKeyAdded(key, attributeName);
849
+ }
850
+ const value = this.element.getAttribute(attributeName);
851
+ if (this.stringMap.get(attributeName) != value) {
852
+ this.stringMapValueChanged(value, key, oldValue);
853
+ }
854
+ if (value == null) {
855
+ const oldValue = this.stringMap.get(attributeName);
856
+ this.stringMap.delete(attributeName);
857
+ if (oldValue)
858
+ this.stringMapKeyRemoved(key, attributeName, oldValue);
859
+ }
860
+ else {
861
+ this.stringMap.set(attributeName, value);
862
+ }
863
+ }
864
+ }
865
+ stringMapKeyAdded(key, attributeName) {
866
+ if (this.delegate.stringMapKeyAdded) {
867
+ this.delegate.stringMapKeyAdded(key, attributeName);
868
+ }
869
+ }
870
+ stringMapValueChanged(value, key, oldValue) {
871
+ if (this.delegate.stringMapValueChanged) {
872
+ this.delegate.stringMapValueChanged(value, key, oldValue);
873
+ }
874
+ }
875
+ stringMapKeyRemoved(key, attributeName, oldValue) {
876
+ if (this.delegate.stringMapKeyRemoved) {
877
+ this.delegate.stringMapKeyRemoved(key, attributeName, oldValue);
878
+ }
879
+ }
880
+ get knownAttributeNames() {
881
+ return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames)));
882
+ }
883
+ get currentAttributeNames() {
884
+ return Array.from(this.element.attributes).map((attribute) => attribute.name);
885
+ }
886
+ get recordedAttributeNames() {
887
+ return Array.from(this.stringMap.keys());
888
+ }
889
+ }
890
+
891
+ class TokenListObserver {
892
+ constructor(element, attributeName, delegate) {
893
+ this.attributeObserver = new AttributeObserver(element, attributeName, this);
894
+ this.delegate = delegate;
895
+ this.tokensByElement = new Multimap();
896
+ }
897
+ get started() {
898
+ return this.attributeObserver.started;
899
+ }
900
+ start() {
901
+ this.attributeObserver.start();
902
+ }
903
+ pause(callback) {
904
+ this.attributeObserver.pause(callback);
905
+ }
906
+ stop() {
907
+ this.attributeObserver.stop();
908
+ }
909
+ refresh() {
910
+ this.attributeObserver.refresh();
911
+ }
912
+ get element() {
913
+ return this.attributeObserver.element;
914
+ }
915
+ get attributeName() {
916
+ return this.attributeObserver.attributeName;
917
+ }
918
+ elementMatchedAttribute(element) {
919
+ this.tokensMatched(this.readTokensForElement(element));
920
+ }
921
+ elementAttributeValueChanged(element) {
922
+ const [unmatchedTokens, matchedTokens] = this.refreshTokensForElement(element);
923
+ this.tokensUnmatched(unmatchedTokens);
924
+ this.tokensMatched(matchedTokens);
925
+ }
926
+ elementUnmatchedAttribute(element) {
927
+ this.tokensUnmatched(this.tokensByElement.getValuesForKey(element));
928
+ }
929
+ tokensMatched(tokens) {
930
+ tokens.forEach((token) => this.tokenMatched(token));
931
+ }
932
+ tokensUnmatched(tokens) {
933
+ tokens.forEach((token) => this.tokenUnmatched(token));
934
+ }
935
+ tokenMatched(token) {
936
+ this.delegate.tokenMatched(token);
937
+ this.tokensByElement.add(token.element, token);
938
+ }
939
+ tokenUnmatched(token) {
940
+ this.delegate.tokenUnmatched(token);
941
+ this.tokensByElement.delete(token.element, token);
942
+ }
943
+ refreshTokensForElement(element) {
944
+ const previousTokens = this.tokensByElement.getValuesForKey(element);
945
+ const currentTokens = this.readTokensForElement(element);
946
+ const firstDifferingIndex = zip(previousTokens, currentTokens).findIndex(([previousToken, currentToken]) => !tokensAreEqual(previousToken, currentToken));
947
+ if (firstDifferingIndex == -1) {
948
+ return [[], []];
949
+ }
950
+ else {
951
+ return [previousTokens.slice(firstDifferingIndex), currentTokens.slice(firstDifferingIndex)];
952
+ }
953
+ }
954
+ readTokensForElement(element) {
955
+ const attributeName = this.attributeName;
956
+ const tokenString = element.getAttribute(attributeName) || "";
957
+ return parseTokenString(tokenString, element, attributeName);
958
+ }
959
+ }
960
+ function parseTokenString(tokenString, element, attributeName) {
961
+ return tokenString
962
+ .trim()
963
+ .split(/\s+/)
964
+ .filter((content) => content.length)
965
+ .map((content, index) => ({ element, attributeName, content, index }));
966
+ }
967
+ function zip(left, right) {
968
+ const length = Math.max(left.length, right.length);
969
+ return Array.from({ length }, (_, index) => [left[index], right[index]]);
970
+ }
971
+ function tokensAreEqual(left, right) {
972
+ return left && right && left.index == right.index && left.content == right.content;
973
+ }
974
+
975
+ class ValueListObserver {
976
+ constructor(element, attributeName, delegate) {
977
+ this.tokenListObserver = new TokenListObserver(element, attributeName, this);
978
+ this.delegate = delegate;
979
+ this.parseResultsByToken = new WeakMap();
980
+ this.valuesByTokenByElement = new WeakMap();
981
+ }
982
+ get started() {
983
+ return this.tokenListObserver.started;
984
+ }
985
+ start() {
986
+ this.tokenListObserver.start();
987
+ }
988
+ stop() {
989
+ this.tokenListObserver.stop();
990
+ }
991
+ refresh() {
992
+ this.tokenListObserver.refresh();
993
+ }
994
+ get element() {
995
+ return this.tokenListObserver.element;
996
+ }
997
+ get attributeName() {
998
+ return this.tokenListObserver.attributeName;
999
+ }
1000
+ tokenMatched(token) {
1001
+ const { element } = token;
1002
+ const { value } = this.fetchParseResultForToken(token);
1003
+ if (value) {
1004
+ this.fetchValuesByTokenForElement(element).set(token, value);
1005
+ this.delegate.elementMatchedValue(element, value);
1006
+ }
1007
+ }
1008
+ tokenUnmatched(token) {
1009
+ const { element } = token;
1010
+ const { value } = this.fetchParseResultForToken(token);
1011
+ if (value) {
1012
+ this.fetchValuesByTokenForElement(element).delete(token);
1013
+ this.delegate.elementUnmatchedValue(element, value);
1014
+ }
1015
+ }
1016
+ fetchParseResultForToken(token) {
1017
+ let parseResult = this.parseResultsByToken.get(token);
1018
+ if (!parseResult) {
1019
+ parseResult = this.parseToken(token);
1020
+ this.parseResultsByToken.set(token, parseResult);
1021
+ }
1022
+ return parseResult;
1023
+ }
1024
+ fetchValuesByTokenForElement(element) {
1025
+ let valuesByToken = this.valuesByTokenByElement.get(element);
1026
+ if (!valuesByToken) {
1027
+ valuesByToken = new Map();
1028
+ this.valuesByTokenByElement.set(element, valuesByToken);
1029
+ }
1030
+ return valuesByToken;
1031
+ }
1032
+ parseToken(token) {
1033
+ try {
1034
+ const value = this.delegate.parseValueForToken(token);
1035
+ return { value };
1036
+ }
1037
+ catch (error) {
1038
+ return { error };
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+ class BindingObserver {
1044
+ constructor(context, delegate) {
1045
+ this.context = context;
1046
+ this.delegate = delegate;
1047
+ this.bindingsByAction = new Map();
1048
+ }
1049
+ start() {
1050
+ if (!this.valueListObserver) {
1051
+ this.valueListObserver = new ValueListObserver(this.element, this.actionAttribute, this);
1052
+ this.valueListObserver.start();
1053
+ }
1054
+ }
1055
+ stop() {
1056
+ if (this.valueListObserver) {
1057
+ this.valueListObserver.stop();
1058
+ delete this.valueListObserver;
1059
+ this.disconnectAllActions();
1060
+ }
1061
+ }
1062
+ get element() {
1063
+ return this.context.element;
1064
+ }
1065
+ get identifier() {
1066
+ return this.context.identifier;
1067
+ }
1068
+ get actionAttribute() {
1069
+ return this.schema.actionAttribute;
1070
+ }
1071
+ get schema() {
1072
+ return this.context.schema;
1073
+ }
1074
+ get bindings() {
1075
+ return Array.from(this.bindingsByAction.values());
1076
+ }
1077
+ connectAction(action) {
1078
+ const binding = new Binding(this.context, action);
1079
+ this.bindingsByAction.set(action, binding);
1080
+ this.delegate.bindingConnected(binding);
1081
+ }
1082
+ disconnectAction(action) {
1083
+ const binding = this.bindingsByAction.get(action);
1084
+ if (binding) {
1085
+ this.bindingsByAction.delete(action);
1086
+ this.delegate.bindingDisconnected(binding);
1087
+ }
1088
+ }
1089
+ disconnectAllActions() {
1090
+ this.bindings.forEach((binding) => this.delegate.bindingDisconnected(binding, true));
1091
+ this.bindingsByAction.clear();
1092
+ }
1093
+ parseValueForToken(token) {
1094
+ const action = Action.forToken(token, this.schema);
1095
+ if (action.identifier == this.identifier) {
1096
+ return action;
1097
+ }
1098
+ }
1099
+ elementMatchedValue(element, action) {
1100
+ this.connectAction(action);
1101
+ }
1102
+ elementUnmatchedValue(element, action) {
1103
+ this.disconnectAction(action);
1104
+ }
1105
+ }
1106
+
1107
+ class ValueObserver {
1108
+ constructor(context, receiver) {
1109
+ this.context = context;
1110
+ this.receiver = receiver;
1111
+ this.stringMapObserver = new StringMapObserver(this.element, this);
1112
+ this.valueDescriptorMap = this.controller.valueDescriptorMap;
1113
+ }
1114
+ start() {
1115
+ this.stringMapObserver.start();
1116
+ this.invokeChangedCallbacksForDefaultValues();
1117
+ }
1118
+ stop() {
1119
+ this.stringMapObserver.stop();
1120
+ }
1121
+ get element() {
1122
+ return this.context.element;
1123
+ }
1124
+ get controller() {
1125
+ return this.context.controller;
1126
+ }
1127
+ getStringMapKeyForAttribute(attributeName) {
1128
+ if (attributeName in this.valueDescriptorMap) {
1129
+ return this.valueDescriptorMap[attributeName].name;
1130
+ }
1131
+ }
1132
+ stringMapKeyAdded(key, attributeName) {
1133
+ const descriptor = this.valueDescriptorMap[attributeName];
1134
+ if (!this.hasValue(key)) {
1135
+ this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), descriptor.writer(descriptor.defaultValue));
1136
+ }
1137
+ }
1138
+ stringMapValueChanged(value, name, oldValue) {
1139
+ const descriptor = this.valueDescriptorNameMap[name];
1140
+ if (value === null)
1141
+ return;
1142
+ if (oldValue === null) {
1143
+ oldValue = descriptor.writer(descriptor.defaultValue);
1144
+ }
1145
+ this.invokeChangedCallback(name, value, oldValue);
1146
+ }
1147
+ stringMapKeyRemoved(key, attributeName, oldValue) {
1148
+ const descriptor = this.valueDescriptorNameMap[key];
1149
+ if (this.hasValue(key)) {
1150
+ this.invokeChangedCallback(key, descriptor.writer(this.receiver[key]), oldValue);
1151
+ }
1152
+ else {
1153
+ this.invokeChangedCallback(key, descriptor.writer(descriptor.defaultValue), oldValue);
1154
+ }
1155
+ }
1156
+ invokeChangedCallbacksForDefaultValues() {
1157
+ for (const { key, name, defaultValue, writer } of this.valueDescriptors) {
1158
+ if (defaultValue != undefined && !this.controller.data.has(key)) {
1159
+ this.invokeChangedCallback(name, writer(defaultValue), undefined);
1160
+ }
1161
+ }
1162
+ }
1163
+ invokeChangedCallback(name, rawValue, rawOldValue) {
1164
+ const changedMethodName = `${name}Changed`;
1165
+ const changedMethod = this.receiver[changedMethodName];
1166
+ if (typeof changedMethod == "function") {
1167
+ const descriptor = this.valueDescriptorNameMap[name];
1168
+ try {
1169
+ const value = descriptor.reader(rawValue);
1170
+ let oldValue = rawOldValue;
1171
+ if (rawOldValue) {
1172
+ oldValue = descriptor.reader(rawOldValue);
1173
+ }
1174
+ changedMethod.call(this.receiver, value, oldValue);
1175
+ }
1176
+ catch (error) {
1177
+ if (error instanceof TypeError) {
1178
+ error.message = `Stimulus Value "${this.context.identifier}.${descriptor.name}" - ${error.message}`;
1179
+ }
1180
+ throw error;
1181
+ }
1182
+ }
1183
+ }
1184
+ get valueDescriptors() {
1185
+ const { valueDescriptorMap } = this;
1186
+ return Object.keys(valueDescriptorMap).map((key) => valueDescriptorMap[key]);
1187
+ }
1188
+ get valueDescriptorNameMap() {
1189
+ const descriptors = {};
1190
+ Object.keys(this.valueDescriptorMap).forEach((key) => {
1191
+ const descriptor = this.valueDescriptorMap[key];
1192
+ descriptors[descriptor.name] = descriptor;
1193
+ });
1194
+ return descriptors;
1195
+ }
1196
+ hasValue(attributeName) {
1197
+ const descriptor = this.valueDescriptorNameMap[attributeName];
1198
+ const hasMethodName = `has${capitalize(descriptor.name)}`;
1199
+ return this.receiver[hasMethodName];
1200
+ }
1201
+ }
1202
+
1203
+ class TargetObserver {
1204
+ constructor(context, delegate) {
1205
+ this.context = context;
1206
+ this.delegate = delegate;
1207
+ this.targetsByName = new Multimap();
1208
+ }
1209
+ start() {
1210
+ if (!this.tokenListObserver) {
1211
+ this.tokenListObserver = new TokenListObserver(this.element, this.attributeName, this);
1212
+ this.tokenListObserver.start();
1213
+ }
1214
+ }
1215
+ stop() {
1216
+ if (this.tokenListObserver) {
1217
+ this.disconnectAllTargets();
1218
+ this.tokenListObserver.stop();
1219
+ delete this.tokenListObserver;
1220
+ }
1221
+ }
1222
+ tokenMatched({ element, content: name }) {
1223
+ if (this.scope.containsElement(element)) {
1224
+ this.connectTarget(element, name);
1225
+ }
1226
+ }
1227
+ tokenUnmatched({ element, content: name }) {
1228
+ this.disconnectTarget(element, name);
1229
+ }
1230
+ connectTarget(element, name) {
1231
+ var _a;
1232
+ if (!this.targetsByName.has(name, element)) {
1233
+ this.targetsByName.add(name, element);
1234
+ (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetConnected(element, name));
1235
+ }
1236
+ }
1237
+ disconnectTarget(element, name) {
1238
+ var _a;
1239
+ if (this.targetsByName.has(name, element)) {
1240
+ this.targetsByName.delete(name, element);
1241
+ (_a = this.tokenListObserver) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.targetDisconnected(element, name));
1242
+ }
1243
+ }
1244
+ disconnectAllTargets() {
1245
+ for (const name of this.targetsByName.keys) {
1246
+ for (const element of this.targetsByName.getValuesForKey(name)) {
1247
+ this.disconnectTarget(element, name);
1248
+ }
1249
+ }
1250
+ }
1251
+ get attributeName() {
1252
+ return `data-${this.context.identifier}-target`;
1253
+ }
1254
+ get element() {
1255
+ return this.context.element;
1256
+ }
1257
+ get scope() {
1258
+ return this.context.scope;
1259
+ }
1260
+ }
1261
+
1262
+ function readInheritableStaticArrayValues(constructor, propertyName) {
1263
+ const ancestors = getAncestorsForConstructor(constructor);
1264
+ return Array.from(ancestors.reduce((values, constructor) => {
1265
+ getOwnStaticArrayValues(constructor, propertyName).forEach((name) => values.add(name));
1266
+ return values;
1267
+ }, new Set()));
1268
+ }
1269
+ function readInheritableStaticObjectPairs(constructor, propertyName) {
1270
+ const ancestors = getAncestorsForConstructor(constructor);
1271
+ return ancestors.reduce((pairs, constructor) => {
1272
+ pairs.push(...getOwnStaticObjectPairs(constructor, propertyName));
1273
+ return pairs;
1274
+ }, []);
1275
+ }
1276
+ function getAncestorsForConstructor(constructor) {
1277
+ const ancestors = [];
1278
+ while (constructor) {
1279
+ ancestors.push(constructor);
1280
+ constructor = Object.getPrototypeOf(constructor);
1281
+ }
1282
+ return ancestors.reverse();
1283
+ }
1284
+ function getOwnStaticArrayValues(constructor, propertyName) {
1285
+ const definition = constructor[propertyName];
1286
+ return Array.isArray(definition) ? definition : [];
1287
+ }
1288
+ function getOwnStaticObjectPairs(constructor, propertyName) {
1289
+ const definition = constructor[propertyName];
1290
+ return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : [];
1291
+ }
1292
+
1293
+ class OutletObserver {
1294
+ constructor(context, delegate) {
1295
+ this.started = false;
1296
+ this.context = context;
1297
+ this.delegate = delegate;
1298
+ this.outletsByName = new Multimap();
1299
+ this.outletElementsByName = new Multimap();
1300
+ this.selectorObserverMap = new Map();
1301
+ this.attributeObserverMap = new Map();
1302
+ }
1303
+ start() {
1304
+ if (!this.started) {
1305
+ this.outletDefinitions.forEach((outletName) => {
1306
+ this.setupSelectorObserverForOutlet(outletName);
1307
+ this.setupAttributeObserverForOutlet(outletName);
1308
+ });
1309
+ this.started = true;
1310
+ this.dependentContexts.forEach((context) => context.refresh());
1311
+ }
1312
+ }
1313
+ refresh() {
1314
+ this.selectorObserverMap.forEach((observer) => observer.refresh());
1315
+ this.attributeObserverMap.forEach((observer) => observer.refresh());
1316
+ }
1317
+ stop() {
1318
+ if (this.started) {
1319
+ this.started = false;
1320
+ this.disconnectAllOutlets();
1321
+ this.stopSelectorObservers();
1322
+ this.stopAttributeObservers();
1323
+ }
1324
+ }
1325
+ stopSelectorObservers() {
1326
+ if (this.selectorObserverMap.size > 0) {
1327
+ this.selectorObserverMap.forEach((observer) => observer.stop());
1328
+ this.selectorObserverMap.clear();
1329
+ }
1330
+ }
1331
+ stopAttributeObservers() {
1332
+ if (this.attributeObserverMap.size > 0) {
1333
+ this.attributeObserverMap.forEach((observer) => observer.stop());
1334
+ this.attributeObserverMap.clear();
1335
+ }
1336
+ }
1337
+ selectorMatched(element, _selector, { outletName }) {
1338
+ const outlet = this.getOutlet(element, outletName);
1339
+ if (outlet) {
1340
+ this.connectOutlet(outlet, element, outletName);
1341
+ }
1342
+ }
1343
+ selectorUnmatched(element, _selector, { outletName }) {
1344
+ const outlet = this.getOutletFromMap(element, outletName);
1345
+ if (outlet) {
1346
+ this.disconnectOutlet(outlet, element, outletName);
1347
+ }
1348
+ }
1349
+ selectorMatchElement(element, { outletName }) {
1350
+ const selector = this.selector(outletName);
1351
+ const hasOutlet = this.hasOutlet(element, outletName);
1352
+ const hasOutletController = element.matches(`[${this.schema.controllerAttribute}~=${outletName}]`);
1353
+ if (selector) {
1354
+ return hasOutlet && hasOutletController && element.matches(selector);
1355
+ }
1356
+ else {
1357
+ return false;
1358
+ }
1359
+ }
1360
+ elementMatchedAttribute(_element, attributeName) {
1361
+ const outletName = this.getOutletNameFromOutletAttributeName(attributeName);
1362
+ if (outletName) {
1363
+ this.updateSelectorObserverForOutlet(outletName);
1364
+ }
1365
+ }
1366
+ elementAttributeValueChanged(_element, attributeName) {
1367
+ const outletName = this.getOutletNameFromOutletAttributeName(attributeName);
1368
+ if (outletName) {
1369
+ this.updateSelectorObserverForOutlet(outletName);
1370
+ }
1371
+ }
1372
+ elementUnmatchedAttribute(_element, attributeName) {
1373
+ const outletName = this.getOutletNameFromOutletAttributeName(attributeName);
1374
+ if (outletName) {
1375
+ this.updateSelectorObserverForOutlet(outletName);
1376
+ }
1377
+ }
1378
+ connectOutlet(outlet, element, outletName) {
1379
+ var _a;
1380
+ if (!this.outletElementsByName.has(outletName, element)) {
1381
+ this.outletsByName.add(outletName, outlet);
1382
+ this.outletElementsByName.add(outletName, element);
1383
+ (_a = this.selectorObserverMap.get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletConnected(outlet, element, outletName));
1384
+ }
1385
+ }
1386
+ disconnectOutlet(outlet, element, outletName) {
1387
+ var _a;
1388
+ if (this.outletElementsByName.has(outletName, element)) {
1389
+ this.outletsByName.delete(outletName, outlet);
1390
+ this.outletElementsByName.delete(outletName, element);
1391
+ (_a = this.selectorObserverMap
1392
+ .get(outletName)) === null || _a === void 0 ? void 0 : _a.pause(() => this.delegate.outletDisconnected(outlet, element, outletName));
1393
+ }
1394
+ }
1395
+ disconnectAllOutlets() {
1396
+ for (const outletName of this.outletElementsByName.keys) {
1397
+ for (const element of this.outletElementsByName.getValuesForKey(outletName)) {
1398
+ for (const outlet of this.outletsByName.getValuesForKey(outletName)) {
1399
+ this.disconnectOutlet(outlet, element, outletName);
1400
+ }
1401
+ }
1402
+ }
1403
+ }
1404
+ updateSelectorObserverForOutlet(outletName) {
1405
+ const observer = this.selectorObserverMap.get(outletName);
1406
+ if (observer) {
1407
+ observer.selector = this.selector(outletName);
1408
+ }
1409
+ }
1410
+ setupSelectorObserverForOutlet(outletName) {
1411
+ const selector = this.selector(outletName);
1412
+ const selectorObserver = new SelectorObserver(document.body, selector, this, { outletName });
1413
+ this.selectorObserverMap.set(outletName, selectorObserver);
1414
+ selectorObserver.start();
1415
+ }
1416
+ setupAttributeObserverForOutlet(outletName) {
1417
+ const attributeName = this.attributeNameForOutletName(outletName);
1418
+ const attributeObserver = new AttributeObserver(this.scope.element, attributeName, this);
1419
+ this.attributeObserverMap.set(outletName, attributeObserver);
1420
+ attributeObserver.start();
1421
+ }
1422
+ selector(outletName) {
1423
+ return this.scope.outlets.getSelectorForOutletName(outletName);
1424
+ }
1425
+ attributeNameForOutletName(outletName) {
1426
+ return this.scope.schema.outletAttributeForScope(this.identifier, outletName);
1427
+ }
1428
+ getOutletNameFromOutletAttributeName(attributeName) {
1429
+ return this.outletDefinitions.find((outletName) => this.attributeNameForOutletName(outletName) === attributeName);
1430
+ }
1431
+ get outletDependencies() {
1432
+ const dependencies = new Multimap();
1433
+ this.router.modules.forEach((module) => {
1434
+ const constructor = module.definition.controllerConstructor;
1435
+ const outlets = readInheritableStaticArrayValues(constructor, "outlets");
1436
+ outlets.forEach((outlet) => dependencies.add(outlet, module.identifier));
1437
+ });
1438
+ return dependencies;
1439
+ }
1440
+ get outletDefinitions() {
1441
+ return this.outletDependencies.getKeysForValue(this.identifier);
1442
+ }
1443
+ get dependentControllerIdentifiers() {
1444
+ return this.outletDependencies.getValuesForKey(this.identifier);
1445
+ }
1446
+ get dependentContexts() {
1447
+ const identifiers = this.dependentControllerIdentifiers;
1448
+ return this.router.contexts.filter((context) => identifiers.includes(context.identifier));
1449
+ }
1450
+ hasOutlet(element, outletName) {
1451
+ return !!this.getOutlet(element, outletName) || !!this.getOutletFromMap(element, outletName);
1452
+ }
1453
+ getOutlet(element, outletName) {
1454
+ return this.application.getControllerForElementAndIdentifier(element, outletName);
1455
+ }
1456
+ getOutletFromMap(element, outletName) {
1457
+ return this.outletsByName.getValuesForKey(outletName).find((outlet) => outlet.element === element);
1458
+ }
1459
+ get scope() {
1460
+ return this.context.scope;
1461
+ }
1462
+ get schema() {
1463
+ return this.context.schema;
1464
+ }
1465
+ get identifier() {
1466
+ return this.context.identifier;
1467
+ }
1468
+ get application() {
1469
+ return this.context.application;
1470
+ }
1471
+ get router() {
1472
+ return this.application.router;
1473
+ }
1474
+ }
1475
+
1476
+ class Context {
1477
+ constructor(module, scope) {
1478
+ this.logDebugActivity = (functionName, detail = {}) => {
1479
+ const { identifier, controller, element } = this;
1480
+ detail = Object.assign({ identifier, controller, element }, detail);
1481
+ this.application.logDebugActivity(this.identifier, functionName, detail);
1482
+ };
1483
+ this.module = module;
1484
+ this.scope = scope;
1485
+ this.controller = new module.controllerConstructor(this);
1486
+ this.bindingObserver = new BindingObserver(this, this.dispatcher);
1487
+ this.valueObserver = new ValueObserver(this, this.controller);
1488
+ this.targetObserver = new TargetObserver(this, this);
1489
+ this.outletObserver = new OutletObserver(this, this);
1490
+ try {
1491
+ this.controller.initialize();
1492
+ this.logDebugActivity("initialize");
1493
+ }
1494
+ catch (error) {
1495
+ this.handleError(error, "initializing controller");
1496
+ }
1497
+ }
1498
+ connect() {
1499
+ this.bindingObserver.start();
1500
+ this.valueObserver.start();
1501
+ this.targetObserver.start();
1502
+ this.outletObserver.start();
1503
+ try {
1504
+ this.controller.connect();
1505
+ this.logDebugActivity("connect");
1506
+ }
1507
+ catch (error) {
1508
+ this.handleError(error, "connecting controller");
1509
+ }
1510
+ }
1511
+ refresh() {
1512
+ this.outletObserver.refresh();
1513
+ }
1514
+ disconnect() {
1515
+ try {
1516
+ this.controller.disconnect();
1517
+ this.logDebugActivity("disconnect");
1518
+ }
1519
+ catch (error) {
1520
+ this.handleError(error, "disconnecting controller");
1521
+ }
1522
+ this.outletObserver.stop();
1523
+ this.targetObserver.stop();
1524
+ this.valueObserver.stop();
1525
+ this.bindingObserver.stop();
1526
+ }
1527
+ get application() {
1528
+ return this.module.application;
1529
+ }
1530
+ get identifier() {
1531
+ return this.module.identifier;
1532
+ }
1533
+ get schema() {
1534
+ return this.application.schema;
1535
+ }
1536
+ get dispatcher() {
1537
+ return this.application.dispatcher;
1538
+ }
1539
+ get element() {
1540
+ return this.scope.element;
1541
+ }
1542
+ get parentElement() {
1543
+ return this.element.parentElement;
1544
+ }
1545
+ handleError(error, message, detail = {}) {
1546
+ const { identifier, controller, element } = this;
1547
+ detail = Object.assign({ identifier, controller, element }, detail);
1548
+ this.application.handleError(error, `Error ${message}`, detail);
1549
+ }
1550
+ targetConnected(element, name) {
1551
+ this.invokeControllerMethod(`${name}TargetConnected`, element);
1552
+ }
1553
+ targetDisconnected(element, name) {
1554
+ this.invokeControllerMethod(`${name}TargetDisconnected`, element);
1555
+ }
1556
+ outletConnected(outlet, element, name) {
1557
+ this.invokeControllerMethod(`${namespaceCamelize(name)}OutletConnected`, outlet, element);
1558
+ }
1559
+ outletDisconnected(outlet, element, name) {
1560
+ this.invokeControllerMethod(`${namespaceCamelize(name)}OutletDisconnected`, outlet, element);
1561
+ }
1562
+ invokeControllerMethod(methodName, ...args) {
1563
+ const controller = this.controller;
1564
+ if (typeof controller[methodName] == "function") {
1565
+ controller[methodName](...args);
1566
+ }
1567
+ }
1568
+ }
1569
+
1570
+ function bless(constructor) {
1571
+ return shadow(constructor, getBlessedProperties(constructor));
1572
+ }
1573
+ function shadow(constructor, properties) {
1574
+ const shadowConstructor = extend(constructor);
1575
+ const shadowProperties = getShadowProperties(constructor.prototype, properties);
1576
+ Object.defineProperties(shadowConstructor.prototype, shadowProperties);
1577
+ return shadowConstructor;
1578
+ }
1579
+ function getBlessedProperties(constructor) {
1580
+ const blessings = readInheritableStaticArrayValues(constructor, "blessings");
1581
+ return blessings.reduce((blessedProperties, blessing) => {
1582
+ const properties = blessing(constructor);
1583
+ for (const key in properties) {
1584
+ const descriptor = blessedProperties[key] || {};
1585
+ blessedProperties[key] = Object.assign(descriptor, properties[key]);
1586
+ }
1587
+ return blessedProperties;
1588
+ }, {});
1589
+ }
1590
+ function getShadowProperties(prototype, properties) {
1591
+ return getOwnKeys(properties).reduce((shadowProperties, key) => {
1592
+ const descriptor = getShadowedDescriptor(prototype, properties, key);
1593
+ if (descriptor) {
1594
+ Object.assign(shadowProperties, { [key]: descriptor });
1595
+ }
1596
+ return shadowProperties;
1597
+ }, {});
1598
+ }
1599
+ function getShadowedDescriptor(prototype, properties, key) {
1600
+ const shadowingDescriptor = Object.getOwnPropertyDescriptor(prototype, key);
1601
+ const shadowedByValue = shadowingDescriptor && "value" in shadowingDescriptor;
1602
+ if (!shadowedByValue) {
1603
+ const descriptor = Object.getOwnPropertyDescriptor(properties, key).value;
1604
+ if (shadowingDescriptor) {
1605
+ descriptor.get = shadowingDescriptor.get || descriptor.get;
1606
+ descriptor.set = shadowingDescriptor.set || descriptor.set;
1607
+ }
1608
+ return descriptor;
1609
+ }
1610
+ }
1611
+ const getOwnKeys = (() => {
1612
+ if (typeof Object.getOwnPropertySymbols == "function") {
1613
+ return (object) => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)];
1614
+ }
1615
+ else {
1616
+ return Object.getOwnPropertyNames;
1617
+ }
1618
+ })();
1619
+ const extend = (() => {
1620
+ function extendWithReflect(constructor) {
1621
+ function extended() {
1622
+ return Reflect.construct(constructor, arguments, new.target);
1623
+ }
1624
+ extended.prototype = Object.create(constructor.prototype, {
1625
+ constructor: { value: extended },
1626
+ });
1627
+ Reflect.setPrototypeOf(extended, constructor);
1628
+ return extended;
1629
+ }
1630
+ function testReflectExtension() {
1631
+ const a = function () {
1632
+ this.a.call(this);
1633
+ };
1634
+ const b = extendWithReflect(a);
1635
+ b.prototype.a = function () { };
1636
+ return new b();
1637
+ }
1638
+ try {
1639
+ testReflectExtension();
1640
+ return extendWithReflect;
1641
+ }
1642
+ catch (error) {
1643
+ return (constructor) => class extended extends constructor {
1644
+ };
1645
+ }
1646
+ })();
1647
+
1648
+ function blessDefinition(definition) {
1649
+ return {
1650
+ identifier: definition.identifier,
1651
+ controllerConstructor: bless(definition.controllerConstructor),
1652
+ };
1653
+ }
1654
+
1655
+ class Module {
1656
+ constructor(application, definition) {
1657
+ this.application = application;
1658
+ this.definition = blessDefinition(definition);
1659
+ this.contextsByScope = new WeakMap();
1660
+ this.connectedContexts = new Set();
1661
+ }
1662
+ get identifier() {
1663
+ return this.definition.identifier;
1664
+ }
1665
+ get controllerConstructor() {
1666
+ return this.definition.controllerConstructor;
1667
+ }
1668
+ get contexts() {
1669
+ return Array.from(this.connectedContexts);
1670
+ }
1671
+ connectContextForScope(scope) {
1672
+ const context = this.fetchContextForScope(scope);
1673
+ this.connectedContexts.add(context);
1674
+ context.connect();
1675
+ }
1676
+ disconnectContextForScope(scope) {
1677
+ const context = this.contextsByScope.get(scope);
1678
+ if (context) {
1679
+ this.connectedContexts.delete(context);
1680
+ context.disconnect();
1681
+ }
1682
+ }
1683
+ fetchContextForScope(scope) {
1684
+ let context = this.contextsByScope.get(scope);
1685
+ if (!context) {
1686
+ context = new Context(this, scope);
1687
+ this.contextsByScope.set(scope, context);
1688
+ }
1689
+ return context;
1690
+ }
1691
+ }
1692
+
1693
+ class ClassMap {
1694
+ constructor(scope) {
1695
+ this.scope = scope;
1696
+ }
1697
+ has(name) {
1698
+ return this.data.has(this.getDataKey(name));
1699
+ }
1700
+ get(name) {
1701
+ return this.getAll(name)[0];
1702
+ }
1703
+ getAll(name) {
1704
+ const tokenString = this.data.get(this.getDataKey(name)) || "";
1705
+ return tokenize(tokenString);
1706
+ }
1707
+ getAttributeName(name) {
1708
+ return this.data.getAttributeNameForKey(this.getDataKey(name));
1709
+ }
1710
+ getDataKey(name) {
1711
+ return `${name}-class`;
1712
+ }
1713
+ get data() {
1714
+ return this.scope.data;
1715
+ }
1716
+ }
1717
+
1718
+ class DataMap {
1719
+ constructor(scope) {
1720
+ this.scope = scope;
1721
+ }
1722
+ get element() {
1723
+ return this.scope.element;
1724
+ }
1725
+ get identifier() {
1726
+ return this.scope.identifier;
1727
+ }
1728
+ get(key) {
1729
+ const name = this.getAttributeNameForKey(key);
1730
+ return this.element.getAttribute(name);
1731
+ }
1732
+ set(key, value) {
1733
+ const name = this.getAttributeNameForKey(key);
1734
+ this.element.setAttribute(name, value);
1735
+ return this.get(key);
1736
+ }
1737
+ has(key) {
1738
+ const name = this.getAttributeNameForKey(key);
1739
+ return this.element.hasAttribute(name);
1740
+ }
1741
+ delete(key) {
1742
+ if (this.has(key)) {
1743
+ const name = this.getAttributeNameForKey(key);
1744
+ this.element.removeAttribute(name);
1745
+ return true;
1746
+ }
1747
+ else {
1748
+ return false;
1749
+ }
1750
+ }
1751
+ getAttributeNameForKey(key) {
1752
+ return `data-${this.identifier}-${dasherize(key)}`;
1753
+ }
1754
+ }
1755
+
1756
+ class Guide {
1757
+ constructor(logger) {
1758
+ this.warnedKeysByObject = new WeakMap();
1759
+ this.logger = logger;
1760
+ }
1761
+ warn(object, key, message) {
1762
+ let warnedKeys = this.warnedKeysByObject.get(object);
1763
+ if (!warnedKeys) {
1764
+ warnedKeys = new Set();
1765
+ this.warnedKeysByObject.set(object, warnedKeys);
1766
+ }
1767
+ if (!warnedKeys.has(key)) {
1768
+ warnedKeys.add(key);
1769
+ this.logger.warn(message, object);
1770
+ }
1771
+ }
1772
+ }
1773
+
1774
+ function attributeValueContainsToken(attributeName, token) {
1775
+ return `[${attributeName}~="${token}"]`;
1776
+ }
1777
+
1778
+ class TargetSet {
1779
+ constructor(scope) {
1780
+ this.scope = scope;
1781
+ }
1782
+ get element() {
1783
+ return this.scope.element;
1784
+ }
1785
+ get identifier() {
1786
+ return this.scope.identifier;
1787
+ }
1788
+ get schema() {
1789
+ return this.scope.schema;
1790
+ }
1791
+ has(targetName) {
1792
+ return this.find(targetName) != null;
1793
+ }
1794
+ find(...targetNames) {
1795
+ return targetNames.reduce((target, targetName) => target || this.findTarget(targetName) || this.findLegacyTarget(targetName), undefined);
1796
+ }
1797
+ findAll(...targetNames) {
1798
+ return targetNames.reduce((targets, targetName) => [
1799
+ ...targets,
1800
+ ...this.findAllTargets(targetName),
1801
+ ...this.findAllLegacyTargets(targetName),
1802
+ ], []);
1803
+ }
1804
+ findTarget(targetName) {
1805
+ const selector = this.getSelectorForTargetName(targetName);
1806
+ return this.scope.findElement(selector);
1807
+ }
1808
+ findAllTargets(targetName) {
1809
+ const selector = this.getSelectorForTargetName(targetName);
1810
+ return this.scope.findAllElements(selector);
1811
+ }
1812
+ getSelectorForTargetName(targetName) {
1813
+ const attributeName = this.schema.targetAttributeForScope(this.identifier);
1814
+ return attributeValueContainsToken(attributeName, targetName);
1815
+ }
1816
+ findLegacyTarget(targetName) {
1817
+ const selector = this.getLegacySelectorForTargetName(targetName);
1818
+ return this.deprecate(this.scope.findElement(selector), targetName);
1819
+ }
1820
+ findAllLegacyTargets(targetName) {
1821
+ const selector = this.getLegacySelectorForTargetName(targetName);
1822
+ return this.scope.findAllElements(selector).map((element) => this.deprecate(element, targetName));
1823
+ }
1824
+ getLegacySelectorForTargetName(targetName) {
1825
+ const targetDescriptor = `${this.identifier}.${targetName}`;
1826
+ return attributeValueContainsToken(this.schema.targetAttribute, targetDescriptor);
1827
+ }
1828
+ deprecate(element, targetName) {
1829
+ if (element) {
1830
+ const { identifier } = this;
1831
+ const attributeName = this.schema.targetAttribute;
1832
+ const revisedAttributeName = this.schema.targetAttributeForScope(identifier);
1833
+ this.guide.warn(element, `target:${targetName}`, `Please replace ${attributeName}="${identifier}.${targetName}" with ${revisedAttributeName}="${targetName}". ` +
1834
+ `The ${attributeName} attribute is deprecated and will be removed in a future version of Stimulus.`);
1835
+ }
1836
+ return element;
1837
+ }
1838
+ get guide() {
1839
+ return this.scope.guide;
1840
+ }
1841
+ }
1842
+
1843
+ class OutletSet {
1844
+ constructor(scope, controllerElement) {
1845
+ this.scope = scope;
1846
+ this.controllerElement = controllerElement;
1847
+ }
1848
+ get element() {
1849
+ return this.scope.element;
1850
+ }
1851
+ get identifier() {
1852
+ return this.scope.identifier;
1853
+ }
1854
+ get schema() {
1855
+ return this.scope.schema;
1856
+ }
1857
+ has(outletName) {
1858
+ return this.find(outletName) != null;
1859
+ }
1860
+ find(...outletNames) {
1861
+ return outletNames.reduce((outlet, outletName) => outlet || this.findOutlet(outletName), undefined);
1862
+ }
1863
+ findAll(...outletNames) {
1864
+ return outletNames.reduce((outlets, outletName) => [...outlets, ...this.findAllOutlets(outletName)], []);
1865
+ }
1866
+ getSelectorForOutletName(outletName) {
1867
+ const attributeName = this.schema.outletAttributeForScope(this.identifier, outletName);
1868
+ return this.controllerElement.getAttribute(attributeName);
1869
+ }
1870
+ findOutlet(outletName) {
1871
+ const selector = this.getSelectorForOutletName(outletName);
1872
+ if (selector)
1873
+ return this.findElement(selector, outletName);
1874
+ }
1875
+ findAllOutlets(outletName) {
1876
+ const selector = this.getSelectorForOutletName(outletName);
1877
+ return selector ? this.findAllElements(selector, outletName) : [];
1878
+ }
1879
+ findElement(selector, outletName) {
1880
+ const elements = this.scope.queryElements(selector);
1881
+ return elements.filter((element) => this.matchesElement(element, selector, outletName))[0];
1882
+ }
1883
+ findAllElements(selector, outletName) {
1884
+ const elements = this.scope.queryElements(selector);
1885
+ return elements.filter((element) => this.matchesElement(element, selector, outletName));
1886
+ }
1887
+ matchesElement(element, selector, outletName) {
1888
+ const controllerAttribute = element.getAttribute(this.scope.schema.controllerAttribute) || "";
1889
+ return element.matches(selector) && controllerAttribute.split(" ").includes(outletName);
1890
+ }
1891
+ }
1892
+
1893
+ class Scope {
1894
+ constructor(schema, element, identifier, logger) {
1895
+ this.targets = new TargetSet(this);
1896
+ this.classes = new ClassMap(this);
1897
+ this.data = new DataMap(this);
1898
+ this.containsElement = (element) => {
1899
+ return element.closest(this.controllerSelector) === this.element;
1900
+ };
1901
+ this.schema = schema;
1902
+ this.element = element;
1903
+ this.identifier = identifier;
1904
+ this.guide = new Guide(logger);
1905
+ this.outlets = new OutletSet(this.documentScope, element);
1906
+ }
1907
+ findElement(selector) {
1908
+ return this.element.matches(selector) ? this.element : this.queryElements(selector).find(this.containsElement);
1909
+ }
1910
+ findAllElements(selector) {
1911
+ return [
1912
+ ...(this.element.matches(selector) ? [this.element] : []),
1913
+ ...this.queryElements(selector).filter(this.containsElement),
1914
+ ];
1915
+ }
1916
+ queryElements(selector) {
1917
+ return Array.from(this.element.querySelectorAll(selector));
1918
+ }
1919
+ get controllerSelector() {
1920
+ return attributeValueContainsToken(this.schema.controllerAttribute, this.identifier);
1921
+ }
1922
+ get isDocumentScope() {
1923
+ return this.element === document.documentElement;
1924
+ }
1925
+ get documentScope() {
1926
+ return this.isDocumentScope
1927
+ ? this
1928
+ : new Scope(this.schema, document.documentElement, this.identifier, this.guide.logger);
1929
+ }
1930
+ }
1931
+
1932
+ class ScopeObserver {
1933
+ constructor(element, schema, delegate) {
1934
+ this.element = element;
1935
+ this.schema = schema;
1936
+ this.delegate = delegate;
1937
+ this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this);
1938
+ this.scopesByIdentifierByElement = new WeakMap();
1939
+ this.scopeReferenceCounts = new WeakMap();
1940
+ }
1941
+ start() {
1942
+ this.valueListObserver.start();
1943
+ }
1944
+ stop() {
1945
+ this.valueListObserver.stop();
1946
+ }
1947
+ get controllerAttribute() {
1948
+ return this.schema.controllerAttribute;
1949
+ }
1950
+ parseValueForToken(token) {
1951
+ const { element, content: identifier } = token;
1952
+ return this.parseValueForElementAndIdentifier(element, identifier);
1953
+ }
1954
+ parseValueForElementAndIdentifier(element, identifier) {
1955
+ const scopesByIdentifier = this.fetchScopesByIdentifierForElement(element);
1956
+ let scope = scopesByIdentifier.get(identifier);
1957
+ if (!scope) {
1958
+ scope = this.delegate.createScopeForElementAndIdentifier(element, identifier);
1959
+ scopesByIdentifier.set(identifier, scope);
1960
+ }
1961
+ return scope;
1962
+ }
1963
+ elementMatchedValue(element, value) {
1964
+ const referenceCount = (this.scopeReferenceCounts.get(value) || 0) + 1;
1965
+ this.scopeReferenceCounts.set(value, referenceCount);
1966
+ if (referenceCount == 1) {
1967
+ this.delegate.scopeConnected(value);
1968
+ }
1969
+ }
1970
+ elementUnmatchedValue(element, value) {
1971
+ const referenceCount = this.scopeReferenceCounts.get(value);
1972
+ if (referenceCount) {
1973
+ this.scopeReferenceCounts.set(value, referenceCount - 1);
1974
+ if (referenceCount == 1) {
1975
+ this.delegate.scopeDisconnected(value);
1976
+ }
1977
+ }
1978
+ }
1979
+ fetchScopesByIdentifierForElement(element) {
1980
+ let scopesByIdentifier = this.scopesByIdentifierByElement.get(element);
1981
+ if (!scopesByIdentifier) {
1982
+ scopesByIdentifier = new Map();
1983
+ this.scopesByIdentifierByElement.set(element, scopesByIdentifier);
1984
+ }
1985
+ return scopesByIdentifier;
1986
+ }
1987
+ }
1988
+
1989
+ class Router {
1990
+ constructor(application) {
1991
+ this.application = application;
1992
+ this.scopeObserver = new ScopeObserver(this.element, this.schema, this);
1993
+ this.scopesByIdentifier = new Multimap();
1994
+ this.modulesByIdentifier = new Map();
1995
+ }
1996
+ get element() {
1997
+ return this.application.element;
1998
+ }
1999
+ get schema() {
2000
+ return this.application.schema;
2001
+ }
2002
+ get logger() {
2003
+ return this.application.logger;
2004
+ }
2005
+ get controllerAttribute() {
2006
+ return this.schema.controllerAttribute;
2007
+ }
2008
+ get modules() {
2009
+ return Array.from(this.modulesByIdentifier.values());
2010
+ }
2011
+ get contexts() {
2012
+ return this.modules.reduce((contexts, module) => contexts.concat(module.contexts), []);
2013
+ }
2014
+ start() {
2015
+ this.scopeObserver.start();
2016
+ }
2017
+ stop() {
2018
+ this.scopeObserver.stop();
2019
+ }
2020
+ loadDefinition(definition) {
2021
+ this.unloadIdentifier(definition.identifier);
2022
+ const module = new Module(this.application, definition);
2023
+ this.connectModule(module);
2024
+ const afterLoad = definition.controllerConstructor.afterLoad;
2025
+ if (afterLoad) {
2026
+ afterLoad.call(definition.controllerConstructor, definition.identifier, this.application);
2027
+ }
2028
+ }
2029
+ unloadIdentifier(identifier) {
2030
+ const module = this.modulesByIdentifier.get(identifier);
2031
+ if (module) {
2032
+ this.disconnectModule(module);
2033
+ }
2034
+ }
2035
+ getContextForElementAndIdentifier(element, identifier) {
2036
+ const module = this.modulesByIdentifier.get(identifier);
2037
+ if (module) {
2038
+ return module.contexts.find((context) => context.element == element);
2039
+ }
2040
+ }
2041
+ proposeToConnectScopeForElementAndIdentifier(element, identifier) {
2042
+ const scope = this.scopeObserver.parseValueForElementAndIdentifier(element, identifier);
2043
+ if (scope) {
2044
+ this.scopeObserver.elementMatchedValue(scope.element, scope);
2045
+ }
2046
+ else {
2047
+ console.error(`Couldn't find or create scope for identifier: "${identifier}" and element:`, element);
2048
+ }
2049
+ }
2050
+ handleError(error, message, detail) {
2051
+ this.application.handleError(error, message, detail);
2052
+ }
2053
+ createScopeForElementAndIdentifier(element, identifier) {
2054
+ return new Scope(this.schema, element, identifier, this.logger);
2055
+ }
2056
+ scopeConnected(scope) {
2057
+ this.scopesByIdentifier.add(scope.identifier, scope);
2058
+ const module = this.modulesByIdentifier.get(scope.identifier);
2059
+ if (module) {
2060
+ module.connectContextForScope(scope);
2061
+ }
2062
+ }
2063
+ scopeDisconnected(scope) {
2064
+ this.scopesByIdentifier.delete(scope.identifier, scope);
2065
+ const module = this.modulesByIdentifier.get(scope.identifier);
2066
+ if (module) {
2067
+ module.disconnectContextForScope(scope);
2068
+ }
2069
+ }
2070
+ connectModule(module) {
2071
+ this.modulesByIdentifier.set(module.identifier, module);
2072
+ const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier);
2073
+ scopes.forEach((scope) => module.connectContextForScope(scope));
2074
+ }
2075
+ disconnectModule(module) {
2076
+ this.modulesByIdentifier.delete(module.identifier);
2077
+ const scopes = this.scopesByIdentifier.getValuesForKey(module.identifier);
2078
+ scopes.forEach((scope) => module.disconnectContextForScope(scope));
2079
+ }
2080
+ }
2081
+
2082
+ const defaultSchema = {
2083
+ controllerAttribute: "data-controller",
2084
+ actionAttribute: "data-action",
2085
+ targetAttribute: "data-target",
2086
+ targetAttributeForScope: (identifier) => `data-${identifier}-target`,
2087
+ outletAttributeForScope: (identifier, outlet) => `data-${identifier}-${outlet}-outlet`,
2088
+ keyMappings: Object.assign(Object.assign({ enter: "Enter", tab: "Tab", esc: "Escape", space: " ", up: "ArrowUp", down: "ArrowDown", left: "ArrowLeft", right: "ArrowRight", home: "Home", end: "End", page_up: "PageUp", page_down: "PageDown" }, objectFromEntries("abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, c]))), objectFromEntries("0123456789".split("").map((n) => [n, n]))),
2089
+ };
2090
+ function objectFromEntries(array) {
2091
+ return array.reduce((memo, [k, v]) => (Object.assign(Object.assign({}, memo), { [k]: v })), {});
2092
+ }
2093
+
2094
+ class Application {
2095
+ constructor(element = document.documentElement, schema = defaultSchema) {
2096
+ this.logger = console;
2097
+ this.debug = false;
2098
+ this.logDebugActivity = (identifier, functionName, detail = {}) => {
2099
+ if (this.debug) {
2100
+ this.logFormattedMessage(identifier, functionName, detail);
2101
+ }
2102
+ };
2103
+ this.element = element;
2104
+ this.schema = schema;
2105
+ this.dispatcher = new Dispatcher(this);
2106
+ this.router = new Router(this);
2107
+ this.actionDescriptorFilters = Object.assign({}, defaultActionDescriptorFilters);
2108
+ }
2109
+ static start(element, schema) {
2110
+ const application = new this(element, schema);
2111
+ application.start();
2112
+ return application;
2113
+ }
2114
+ async start() {
2115
+ await domReady();
2116
+ this.logDebugActivity("application", "starting");
2117
+ this.dispatcher.start();
2118
+ this.router.start();
2119
+ this.logDebugActivity("application", "start");
2120
+ }
2121
+ stop() {
2122
+ this.logDebugActivity("application", "stopping");
2123
+ this.dispatcher.stop();
2124
+ this.router.stop();
2125
+ this.logDebugActivity("application", "stop");
2126
+ }
2127
+ register(identifier, controllerConstructor) {
2128
+ this.load({ identifier, controllerConstructor });
2129
+ }
2130
+ registerActionOption(name, filter) {
2131
+ this.actionDescriptorFilters[name] = filter;
2132
+ }
2133
+ load(head, ...rest) {
2134
+ const definitions = Array.isArray(head) ? head : [head, ...rest];
2135
+ definitions.forEach((definition) => {
2136
+ if (definition.controllerConstructor.shouldLoad) {
2137
+ this.router.loadDefinition(definition);
2138
+ }
2139
+ });
2140
+ }
2141
+ unload(head, ...rest) {
2142
+ const identifiers = Array.isArray(head) ? head : [head, ...rest];
2143
+ identifiers.forEach((identifier) => this.router.unloadIdentifier(identifier));
2144
+ }
2145
+ get controllers() {
2146
+ return this.router.contexts.map((context) => context.controller);
2147
+ }
2148
+ getControllerForElementAndIdentifier(element, identifier) {
2149
+ const context = this.router.getContextForElementAndIdentifier(element, identifier);
2150
+ return context ? context.controller : null;
2151
+ }
2152
+ handleError(error, message, detail) {
2153
+ var _a;
2154
+ this.logger.error(`%s\n\n%o\n\n%o`, message, error, detail);
2155
+ (_a = window.onerror) === null || _a === void 0 ? void 0 : _a.call(window, message, "", 0, 0, error);
2156
+ }
2157
+ logFormattedMessage(identifier, functionName, detail = {}) {
2158
+ detail = Object.assign({ application: this }, detail);
2159
+ this.logger.groupCollapsed(`${identifier} #${functionName}`);
2160
+ this.logger.log("details:", Object.assign({}, detail));
2161
+ this.logger.groupEnd();
2162
+ }
2163
+ }
2164
+ function domReady() {
2165
+ return new Promise((resolve) => {
2166
+ if (document.readyState == "loading") {
2167
+ document.addEventListener("DOMContentLoaded", () => resolve());
2168
+ }
2169
+ else {
2170
+ resolve();
2171
+ }
2172
+ });
2173
+ }
2174
+
2175
+ function ClassPropertiesBlessing(constructor) {
2176
+ const classes = readInheritableStaticArrayValues(constructor, "classes");
2177
+ return classes.reduce((properties, classDefinition) => {
2178
+ return Object.assign(properties, propertiesForClassDefinition(classDefinition));
2179
+ }, {});
2180
+ }
2181
+ function propertiesForClassDefinition(key) {
2182
+ return {
2183
+ [`${key}Class`]: {
2184
+ get() {
2185
+ const { classes } = this;
2186
+ if (classes.has(key)) {
2187
+ return classes.get(key);
2188
+ }
2189
+ else {
2190
+ const attribute = classes.getAttributeName(key);
2191
+ throw new Error(`Missing attribute "${attribute}"`);
2192
+ }
2193
+ },
2194
+ },
2195
+ [`${key}Classes`]: {
2196
+ get() {
2197
+ return this.classes.getAll(key);
2198
+ },
2199
+ },
2200
+ [`has${capitalize(key)}Class`]: {
2201
+ get() {
2202
+ return this.classes.has(key);
2203
+ },
2204
+ },
2205
+ };
2206
+ }
2207
+
2208
+ function OutletPropertiesBlessing(constructor) {
2209
+ const outlets = readInheritableStaticArrayValues(constructor, "outlets");
2210
+ return outlets.reduce((properties, outletDefinition) => {
2211
+ return Object.assign(properties, propertiesForOutletDefinition(outletDefinition));
2212
+ }, {});
2213
+ }
2214
+ function getOutletController(controller, element, identifier) {
2215
+ return controller.application.getControllerForElementAndIdentifier(element, identifier);
2216
+ }
2217
+ function getControllerAndEnsureConnectedScope(controller, element, outletName) {
2218
+ let outletController = getOutletController(controller, element, outletName);
2219
+ if (outletController)
2220
+ return outletController;
2221
+ controller.application.router.proposeToConnectScopeForElementAndIdentifier(element, outletName);
2222
+ outletController = getOutletController(controller, element, outletName);
2223
+ if (outletController)
2224
+ return outletController;
2225
+ }
2226
+ function propertiesForOutletDefinition(name) {
2227
+ const camelizedName = namespaceCamelize(name);
2228
+ return {
2229
+ [`${camelizedName}Outlet`]: {
2230
+ get() {
2231
+ const outletElement = this.outlets.find(name);
2232
+ const selector = this.outlets.getSelectorForOutletName(name);
2233
+ if (outletElement) {
2234
+ const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);
2235
+ if (outletController)
2236
+ return outletController;
2237
+ throw new Error(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`);
2238
+ }
2239
+ throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`);
2240
+ },
2241
+ },
2242
+ [`${camelizedName}Outlets`]: {
2243
+ get() {
2244
+ const outlets = this.outlets.findAll(name);
2245
+ if (outlets.length > 0) {
2246
+ return outlets
2247
+ .map((outletElement) => {
2248
+ const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);
2249
+ if (outletController)
2250
+ return outletController;
2251
+ console.warn(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`, outletElement);
2252
+ })
2253
+ .filter((controller) => controller);
2254
+ }
2255
+ return [];
2256
+ },
2257
+ },
2258
+ [`${camelizedName}OutletElement`]: {
2259
+ get() {
2260
+ const outletElement = this.outlets.find(name);
2261
+ const selector = this.outlets.getSelectorForOutletName(name);
2262
+ if (outletElement) {
2263
+ return outletElement;
2264
+ }
2265
+ else {
2266
+ throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`);
2267
+ }
2268
+ },
2269
+ },
2270
+ [`${camelizedName}OutletElements`]: {
2271
+ get() {
2272
+ return this.outlets.findAll(name);
2273
+ },
2274
+ },
2275
+ [`has${capitalize(camelizedName)}Outlet`]: {
2276
+ get() {
2277
+ return this.outlets.has(name);
2278
+ },
2279
+ },
2280
+ };
2281
+ }
2282
+
2283
+ function TargetPropertiesBlessing(constructor) {
2284
+ const targets = readInheritableStaticArrayValues(constructor, "targets");
2285
+ return targets.reduce((properties, targetDefinition) => {
2286
+ return Object.assign(properties, propertiesForTargetDefinition(targetDefinition));
2287
+ }, {});
2288
+ }
2289
+ function propertiesForTargetDefinition(name) {
2290
+ return {
2291
+ [`${name}Target`]: {
2292
+ get() {
2293
+ const target = this.targets.find(name);
2294
+ if (target) {
2295
+ return target;
2296
+ }
2297
+ else {
2298
+ throw new Error(`Missing target element "${name}" for "${this.identifier}" controller`);
2299
+ }
2300
+ },
2301
+ },
2302
+ [`${name}Targets`]: {
2303
+ get() {
2304
+ return this.targets.findAll(name);
2305
+ },
2306
+ },
2307
+ [`has${capitalize(name)}Target`]: {
2308
+ get() {
2309
+ return this.targets.has(name);
2310
+ },
2311
+ },
2312
+ };
2313
+ }
2314
+
2315
+ function ValuePropertiesBlessing(constructor) {
2316
+ const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values");
2317
+ const propertyDescriptorMap = {
2318
+ valueDescriptorMap: {
2319
+ get() {
2320
+ return valueDefinitionPairs.reduce((result, valueDefinitionPair) => {
2321
+ const valueDescriptor = parseValueDefinitionPair(valueDefinitionPair, this.identifier);
2322
+ const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key);
2323
+ return Object.assign(result, { [attributeName]: valueDescriptor });
2324
+ }, {});
2325
+ },
2326
+ },
2327
+ };
2328
+ return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => {
2329
+ return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair));
2330
+ }, propertyDescriptorMap);
2331
+ }
2332
+ function propertiesForValueDefinitionPair(valueDefinitionPair, controller) {
2333
+ const definition = parseValueDefinitionPair(valueDefinitionPair, controller);
2334
+ const { key, name, reader: read, writer: write } = definition;
2335
+ return {
2336
+ [name]: {
2337
+ get() {
2338
+ const value = this.data.get(key);
2339
+ if (value !== null) {
2340
+ return read(value);
2341
+ }
2342
+ else {
2343
+ return definition.defaultValue;
2344
+ }
2345
+ },
2346
+ set(value) {
2347
+ if (value === undefined) {
2348
+ this.data.delete(key);
2349
+ }
2350
+ else {
2351
+ this.data.set(key, write(value));
2352
+ }
2353
+ },
2354
+ },
2355
+ [`has${capitalize(name)}`]: {
2356
+ get() {
2357
+ return this.data.has(key) || definition.hasCustomDefaultValue;
2358
+ },
2359
+ },
2360
+ };
2361
+ }
2362
+ function parseValueDefinitionPair([token, typeDefinition], controller) {
2363
+ return valueDescriptorForTokenAndTypeDefinition({
2364
+ controller,
2365
+ token,
2366
+ typeDefinition,
2367
+ });
2368
+ }
2369
+ function parseValueTypeConstant(constant) {
2370
+ switch (constant) {
2371
+ case Array:
2372
+ return "array";
2373
+ case Boolean:
2374
+ return "boolean";
2375
+ case Number:
2376
+ return "number";
2377
+ case Object:
2378
+ return "object";
2379
+ case String:
2380
+ return "string";
2381
+ }
2382
+ }
2383
+ function parseValueTypeDefault(defaultValue) {
2384
+ switch (typeof defaultValue) {
2385
+ case "boolean":
2386
+ return "boolean";
2387
+ case "number":
2388
+ return "number";
2389
+ case "string":
2390
+ return "string";
2391
+ }
2392
+ if (Array.isArray(defaultValue))
2393
+ return "array";
2394
+ if (Object.prototype.toString.call(defaultValue) === "[object Object]")
2395
+ return "object";
2396
+ }
2397
+ function parseValueTypeObject(payload) {
2398
+ const { controller, token, typeObject } = payload;
2399
+ const hasType = isSomething(typeObject.type);
2400
+ const hasDefault = isSomething(typeObject.default);
2401
+ const fullObject = hasType && hasDefault;
2402
+ const onlyType = hasType && !hasDefault;
2403
+ const onlyDefault = !hasType && hasDefault;
2404
+ const typeFromObject = parseValueTypeConstant(typeObject.type);
2405
+ const typeFromDefaultValue = parseValueTypeDefault(payload.typeObject.default);
2406
+ if (onlyType)
2407
+ return typeFromObject;
2408
+ if (onlyDefault)
2409
+ return typeFromDefaultValue;
2410
+ if (typeFromObject !== typeFromDefaultValue) {
2411
+ const propertyPath = controller ? `${controller}.${token}` : token;
2412
+ throw new Error(`The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${typeObject.default}" is of type "${typeFromDefaultValue}".`);
2413
+ }
2414
+ if (fullObject)
2415
+ return typeFromObject;
2416
+ }
2417
+ function parseValueTypeDefinition(payload) {
2418
+ const { controller, token, typeDefinition } = payload;
2419
+ const typeObject = { controller, token, typeObject: typeDefinition };
2420
+ const typeFromObject = parseValueTypeObject(typeObject);
2421
+ const typeFromDefaultValue = parseValueTypeDefault(typeDefinition);
2422
+ const typeFromConstant = parseValueTypeConstant(typeDefinition);
2423
+ const type = typeFromObject || typeFromDefaultValue || typeFromConstant;
2424
+ if (type)
2425
+ return type;
2426
+ const propertyPath = controller ? `${controller}.${typeDefinition}` : token;
2427
+ throw new Error(`Unknown value type "${propertyPath}" for "${token}" value`);
2428
+ }
2429
+ function defaultValueForDefinition(typeDefinition) {
2430
+ const constant = parseValueTypeConstant(typeDefinition);
2431
+ if (constant)
2432
+ return defaultValuesByType[constant];
2433
+ const hasDefault = hasProperty(typeDefinition, "default");
2434
+ const hasType = hasProperty(typeDefinition, "type");
2435
+ const typeObject = typeDefinition;
2436
+ if (hasDefault)
2437
+ return typeObject.default;
2438
+ if (hasType) {
2439
+ const { type } = typeObject;
2440
+ const constantFromType = parseValueTypeConstant(type);
2441
+ if (constantFromType)
2442
+ return defaultValuesByType[constantFromType];
2443
+ }
2444
+ return typeDefinition;
2445
+ }
2446
+ function valueDescriptorForTokenAndTypeDefinition(payload) {
2447
+ const { token, typeDefinition } = payload;
2448
+ const key = `${dasherize(token)}-value`;
2449
+ const type = parseValueTypeDefinition(payload);
2450
+ return {
2451
+ type,
2452
+ key,
2453
+ name: camelize(key),
2454
+ get defaultValue() {
2455
+ return defaultValueForDefinition(typeDefinition);
2456
+ },
2457
+ get hasCustomDefaultValue() {
2458
+ return parseValueTypeDefault(typeDefinition) !== undefined;
2459
+ },
2460
+ reader: readers[type],
2461
+ writer: writers[type] || writers.default,
2462
+ };
2463
+ }
2464
+ const defaultValuesByType = {
2465
+ get array() {
2466
+ return [];
2467
+ },
2468
+ boolean: false,
2469
+ number: 0,
2470
+ get object() {
2471
+ return {};
2472
+ },
2473
+ string: "",
2474
+ };
2475
+ const readers = {
2476
+ array(value) {
2477
+ const array = JSON.parse(value);
2478
+ if (!Array.isArray(array)) {
2479
+ throw new TypeError(`expected value of type "array" but instead got value "${value}" of type "${parseValueTypeDefault(array)}"`);
2480
+ }
2481
+ return array;
2482
+ },
2483
+ boolean(value) {
2484
+ return !(value == "0" || String(value).toLowerCase() == "false");
2485
+ },
2486
+ number(value) {
2487
+ return Number(value.replace(/_/g, ""));
2488
+ },
2489
+ object(value) {
2490
+ const object = JSON.parse(value);
2491
+ if (object === null || typeof object != "object" || Array.isArray(object)) {
2492
+ throw new TypeError(`expected value of type "object" but instead got value "${value}" of type "${parseValueTypeDefault(object)}"`);
2493
+ }
2494
+ return object;
2495
+ },
2496
+ string(value) {
2497
+ return value;
2498
+ },
2499
+ };
2500
+ const writers = {
2501
+ default: writeString,
2502
+ array: writeJSON,
2503
+ object: writeJSON,
2504
+ };
2505
+ function writeJSON(value) {
2506
+ return JSON.stringify(value);
2507
+ }
2508
+ function writeString(value) {
2509
+ return `${value}`;
2510
+ }
2511
+
2512
+ class Controller {
2513
+ constructor(context) {
2514
+ this.context = context;
2515
+ }
2516
+ static get shouldLoad() {
2517
+ return true;
2518
+ }
2519
+ static afterLoad(_identifier, _application) {
2520
+ return;
2521
+ }
2522
+ get application() {
2523
+ return this.context.application;
2524
+ }
2525
+ get scope() {
2526
+ return this.context.scope;
2527
+ }
2528
+ get element() {
2529
+ return this.scope.element;
2530
+ }
2531
+ get identifier() {
2532
+ return this.scope.identifier;
2533
+ }
2534
+ get targets() {
2535
+ return this.scope.targets;
2536
+ }
2537
+ get outlets() {
2538
+ return this.scope.outlets;
2539
+ }
2540
+ get classes() {
2541
+ return this.scope.classes;
2542
+ }
2543
+ get data() {
2544
+ return this.scope.data;
2545
+ }
2546
+ initialize() {
2547
+ }
2548
+ connect() {
2549
+ }
2550
+ disconnect() {
2551
+ }
2552
+ dispatch(eventName, { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true, } = {}) {
2553
+ const type = prefix ? `${prefix}:${eventName}` : eventName;
2554
+ const event = new CustomEvent(type, { detail, bubbles, cancelable });
2555
+ target.dispatchEvent(event);
2556
+ return event;
2557
+ }
2558
+ }
2559
+ Controller.blessings = [
2560
+ ClassPropertiesBlessing,
2561
+ TargetPropertiesBlessing,
2562
+ ValuePropertiesBlessing,
2563
+ OutletPropertiesBlessing,
2564
+ ];
2565
+ Controller.targets = [];
2566
+ Controller.outlets = [];
2567
+ Controller.values = {};
2568
+
2569
+ exports.Application = Application;
2570
+ exports.AttributeObserver = AttributeObserver;
2571
+ exports.Context = Context;
2572
+ exports.Controller = Controller;
2573
+ exports.ElementObserver = ElementObserver;
2574
+ exports.IndexedMultimap = IndexedMultimap;
2575
+ exports.Multimap = Multimap;
2576
+ exports.SelectorObserver = SelectorObserver;
2577
+ exports.StringMapObserver = StringMapObserver;
2578
+ exports.TokenListObserver = TokenListObserver;
2579
+ exports.ValueListObserver = ValueListObserver;
2580
+ exports.add = add;
2581
+ exports.defaultSchema = defaultSchema;
2582
+ exports.del = del;
2583
+ exports.fetch = fetch;
2584
+ exports.prune = prune;
2585
+
2586
+ Object.defineProperty(exports, '__esModule', { value: true });
2587
+
2588
+ })));