create-yss-spec 3.5.2 → 3.5.4

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 (2050) hide show
  1. package/package.json +1 -1
  2. package/src/template/asset-runtime.js +23 -6
  3. package/template/.agents/skills/.strategic-design-skills-manifest.json +5 -5
  4. package/template/.agents/skills/archify/SKILL.md +4 -52
  5. package/template/.agents/skills/archify/references/authoring-notes.md +12 -0
  6. package/template/.agents/skills/archify/references/authoring-workflow.md +25 -0
  7. package/template/.agents/skills/archify/references/delivery-workflow.md +25 -0
  8. package/template/.agents/skills/archify/references/upstream-updates.md +12 -0
  9. package/template/.agents/skills/code-review/SKILL.md +3 -34
  10. package/template/.agents/skills/code-review/references/legacy-convergence.md +5 -0
  11. package/template/.agents/skills/code-review/references/review-axis-checklists.md +18 -0
  12. package/template/.agents/skills/code-review/references/smell-baseline.md +23 -0
  13. package/template/.agents/skills/codebase-design/SKILL.md +4 -0
  14. package/template/.agents/skills/codebase-design/references/architecture-audit.md +69 -0
  15. package/template/.agents/skills/diagnosing-bugs/SKILL.md +3 -91
  16. package/template/.agents/skills/diagnosing-bugs/references/feedback-loop.md +53 -0
  17. package/template/.agents/skills/diagnosing-bugs/references/investigation.md +49 -0
  18. package/template/.agents/skills/frontend-commit/SKILL.md +4 -93
  19. package/template/.agents/skills/git-commit-core/SKILL.md +18 -0
  20. package/template/.agents/skills/git-commit-core/agents/openai.yaml +2 -0
  21. package/template/.agents/skills/java-backend-commit/SKILL.md +4 -96
  22. package/template/.agents/skills/llm-wiki/SKILL.md +12 -13
  23. package/template/.agents/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
  24. package/template/.agents/skills/llm-wiki/references/compile.md +21 -114
  25. package/template/.agents/skills/llm-wiki/references/ingest.md +8 -33
  26. package/template/.agents/skills/llm-wiki/references/lint.md +9 -46
  27. package/template/.agents/skills/llm-wiki/references/query.md +9 -18
  28. package/template/.agents/skills/llm-wiki/references/schema.md +56 -29
  29. package/template/.agents/skills/llm-wiki/references/transactions.md +48 -0
  30. package/template/.agents/skills/llm-wiki/references/writing.md +4 -4
  31. package/template/.agents/skills/llm-wiki/scripts/advise.mjs +46 -58
  32. package/template/.agents/skills/llm-wiki/scripts/advise.test.mjs +11 -16
  33. package/template/.agents/skills/llm-wiki/scripts/core.mjs +262 -0
  34. package/template/.agents/skills/llm-wiki/scripts/extract.mjs +35 -18
  35. package/template/.agents/skills/llm-wiki/scripts/extract.test.mjs +5 -8
  36. package/template/.agents/skills/llm-wiki/scripts/feedback.mjs +51 -0
  37. package/template/.agents/skills/llm-wiki/scripts/inventory.mjs +43 -171
  38. package/template/.agents/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
  39. package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
  40. package/template/.agents/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
  41. package/template/.agents/skills/llm-wiki/scripts/migrate.mjs +51 -0
  42. package/template/.agents/skills/llm-wiki/scripts/query.mjs +149 -0
  43. package/template/.agents/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
  44. package/template/.agents/skills/llm-wiki/scripts/sources.mjs +166 -0
  45. package/template/.agents/skills/llm-wiki/scripts/transaction.mjs +384 -0
  46. package/template/.agents/skills/llm-wiki/scripts/v2.test.mjs +354 -0
  47. package/template/.agents/skills/maintaining-skills/references/authoring.md +6 -0
  48. package/template/.agents/skills/prototype/LOGIC.md +1 -1
  49. package/template/.agents/skills/prototype/SKILL.md +5 -19
  50. package/template/.agents/skills/prototype-review/SKILL.md +11 -0
  51. package/template/.agents/skills/prototype-review/references/component-qa.md +32 -0
  52. package/template/.agents/skills/setup-matt-pocock-skills/SKILL.md +4 -74
  53. package/template/.agents/skills/setup-matt-pocock-skills/references/configuration-decisions.md +42 -0
  54. package/template/.agents/skills/setup-matt-pocock-skills/references/write-configuration.md +42 -0
  55. package/template/.agents/skills/to-spec/SKILL.md +9 -62
  56. package/template/.agents/skills/to-tickets/SKILL.md +20 -86
  57. package/template/.agents/skills/using-git-worktrees/SKILL.md +5 -122
  58. package/template/.agents/skills/using-git-worktrees/references/git-fallback.md +46 -0
  59. package/template/.agents/skills/using-git-worktrees/references/setup-and-baseline.md +45 -0
  60. package/template/.agents/skills/using-git-worktrees/references/troubleshooting.md +47 -0
  61. package/template/.agents/skills/wayfinder/SKILL.md +7 -86
  62. package/template/.agents/skills/wayfinder/references/chart-map.md +14 -0
  63. package/template/.agents/skills/wayfinder/references/map-format.md +49 -0
  64. package/template/.agents/skills/wayfinder/references/scope-and-frontier.md +24 -0
  65. package/template/.agents/skills/wayfinder/references/ticket-types.md +12 -0
  66. package/template/.agents/skills/wayfinder/references/work-map.md +15 -0
  67. package/template/.agents/skills/writing-for-agents/SKILL-MECHANICS.md +20 -11
  68. package/template/.agents/skills/yedit-table-usage/SKILL.md +5 -172
  69. package/template/.agents/skills/yedit-table-usage/references/editable-table-example.md +141 -0
  70. package/template/.agents/skills/yedit-table-usage/references/select-and-filter-examples.md +38 -0
  71. package/template/.agents/skills/yss-ddd-scaffold-generator/SKILL.md +4 -25
  72. package/template/.agents/skills/yss-ddd-scaffold-generator/references/engineering-checks.md +11 -0
  73. package/template/.agents/skills/yss-ddd-scaffold-generator/references/generation-workflow.md +14 -0
  74. package/template/.agents/skills/yss-ddd-scaffold-generator/references/platform-selection.md +16 -0
  75. package/template/.agents/skills/yss-design-system/SKILL.md +13 -3
  76. package/template/.agents/skills/yss-design-system/assets/enterprise-craft/app.js +53 -0
  77. package/template/.agents/skills/yss-design-system/assets/enterprise-craft/index.html +2 -0
  78. package/template/.agents/skills/yss-design-system/assets/enterprise-craft/scenarios.js +14 -0
  79. package/template/.agents/skills/yss-design-system/assets/enterprise-craft/styles.css +32 -0
  80. package/template/.agents/skills/yss-design-system/references/data-quality-theme.md +2 -2
  81. package/template/.agents/skills/yss-design-system/references/design-qa-theme.md +1 -1
  82. package/template/.agents/skills/yss-design-system/references/design-system.md +3 -3
  83. package/template/.agents/skills/yss-design-system/references/enterprise-craft.md +33 -0
  84. package/template/.agents/skills/yss-design-system/references/page-composition.md +24 -0
  85. package/template/.agents/skills/yss-design-system/references/prototype-default-theme.md +26 -0
  86. package/template/.agents/skills/yss-design-system/references/search-date-theme.md +19 -0
  87. package/template/.agents/skills/yss-design-system/scripts/export-craft-examples.mjs +30 -0
  88. package/template/.agents/skills/yss-hook/SKILL.md +8 -102
  89. package/template/.agents/skills/yss-hook/references/async-actions.md +49 -0
  90. package/template/.agents/skills/yss-hook/references/list-pagination.md +46 -0
  91. package/template/.agents/skills/yss-hook/references/polling.md +20 -0
  92. package/template/.agents/skills/yss-implementation-contract-compiler/SKILL.md +8 -3
  93. package/template/.agents/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
  94. package/template/.agents/skills/yss-implementation-contract-compiler/references/scaffold-compilation.md +7 -0
  95. package/template/.agents/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
  96. package/template/.agents/skills/yss-openapi-draft-review/SKILL.md +2 -49
  97. package/template/.agents/skills/yss-openapi-draft-review/references/review-output.md +45 -0
  98. package/template/.agents/skills/yss-openapi-draft-review/references/semantic-review.md +16 -0
  99. package/template/.agents/skills/yss-openapi-governance/SKILL.md +2 -48
  100. package/template/.agents/skills/yss-openapi-governance/references/governance-workflow.md +38 -0
  101. package/template/.agents/skills/yss-openapi-governance/references/locked-toolchain.md +22 -0
  102. package/template/.agents/skills/yss-product-lifecycle/SKILL.md +24 -20
  103. package/template/.agents/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
  104. package/template/.agents/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
  105. package/template/.agents/skills/yss-product-lifecycle/references/orchestration-contract.yaml +429 -384
  106. package/template/.agents/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  107. package/template/.agents/skills/yss-product-lifecycle/references/plan-requirements.md +12 -0
  108. package/template/.agents/skills/yss-product-lifecycle/references/state-model.md +3 -3
  109. package/template/.agents/skills/yss-prototype-stage/SKILL.md +27 -8
  110. package/template/.agents/skills/yss-prototype-stage/assets/comparison/comparison.css +12 -0
  111. package/template/.agents/skills/yss-prototype-stage/assets/comparison/comparison.js +52 -0
  112. package/template/.agents/skills/yss-prototype-stage/assets/comparison/index.html +6 -0
  113. package/template/.agents/skills/yss-prototype-stage/assets/comparison/review-ready.js +2 -0
  114. package/template/.agents/skills/yss-prototype-stage/assets/low-fidelity-exercise/app.js +17 -0
  115. package/template/.agents/skills/yss-prototype-stage/assets/low-fidelity-exercise/index.html +1 -0
  116. package/template/.agents/skills/yss-prototype-stage/assets/low-fidelity-exercise/styles.css +1 -0
  117. package/template/.agents/skills/yss-prototype-stage/assets/native-workbench/app.js +12 -6
  118. package/template/.agents/skills/yss-prototype-stage/assets/native-workbench/index.html +1 -1
  119. package/template/.agents/skills/yss-prototype-stage/assets/native-workbench/scenarios.json +297 -0
  120. package/template/.agents/skills/yss-prototype-stage/assets/native-workbench/styles.css +2 -0
  121. package/template/.agents/skills/yss-prototype-stage/assets/offline-html/app.js +7 -5
  122. package/template/.agents/skills/yss-prototype-stage/assets/offline-html/scenarios.json +297 -0
  123. package/template/.agents/skills/yss-prototype-stage/assets/prototype-theme.css +92 -0
  124. package/template/.agents/skills/yss-prototype-stage/assets/scenario-runtime.js +22 -0
  125. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/SHADCN-LICENSE.txt +21 -0
  126. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/package.json +23 -0
  127. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/pnpm-lock.yaml +1278 -0
  128. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/registry-manifest.json +936 -0
  129. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/theme.css +107 -0
  130. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/Alert.vue +21 -0
  131. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/AlertDescription.vue +17 -0
  132. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/AlertTitle.vue +17 -0
  133. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/index.ts +24 -0
  134. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialog.vue +15 -0
  135. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogAction.vue +18 -0
  136. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogCancel.vue +25 -0
  137. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogContent.vue +44 -0
  138. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogDescription.vue +23 -0
  139. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogFooter.vue +22 -0
  140. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogHeader.vue +17 -0
  141. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogTitle.vue +21 -0
  142. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
  143. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/index.ts +9 -0
  144. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/badge/Badge.vue +26 -0
  145. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/badge/index.ts +26 -0
  146. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/Breadcrumb.vue +17 -0
  147. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbEllipsis.vue +23 -0
  148. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbItem.vue +17 -0
  149. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbLink.vue +21 -0
  150. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbList.vue +17 -0
  151. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbPage.vue +20 -0
  152. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbSeparator.vue +22 -0
  153. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/index.ts +7 -0
  154. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/button/Button.vue +31 -0
  155. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/button/index.ts +40 -0
  156. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/Card.vue +22 -0
  157. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardAction.vue +17 -0
  158. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardContent.vue +17 -0
  159. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardDescription.vue +17 -0
  160. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardFooter.vue +17 -0
  161. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardHeader.vue +17 -0
  162. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardTitle.vue +17 -0
  163. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/index.ts +7 -0
  164. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/checkbox/Checkbox.vue +35 -0
  165. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/checkbox/index.ts +1 -0
  166. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/Combobox.vue +19 -0
  167. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxAnchor.vue +23 -0
  168. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxEmpty.vue +21 -0
  169. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxGroup.vue +27 -0
  170. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxInput.vue +42 -0
  171. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxItem.vue +24 -0
  172. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxItemIndicator.vue +23 -0
  173. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxList.vue +33 -0
  174. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxSeparator.vue +21 -0
  175. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxTrigger.vue +24 -0
  176. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxViewport.vue +23 -0
  177. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/index.ts +13 -0
  178. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/Dialog.vue +19 -0
  179. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogClose.vue +15 -0
  180. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogContent.vue +53 -0
  181. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogDescription.vue +23 -0
  182. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogFooter.vue +27 -0
  183. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogHeader.vue +17 -0
  184. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogOverlay.vue +21 -0
  185. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogScrollContent.vue +59 -0
  186. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogTitle.vue +23 -0
  187. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogTrigger.vue +15 -0
  188. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/index.ts +10 -0
  189. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenu.vue +19 -0
  190. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
  191. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
  192. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuGroup.vue +15 -0
  193. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuItem.vue +31 -0
  194. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
  195. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  196. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  197. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  198. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  199. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
  200. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
  201. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  202. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  203. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/index.ts +16 -0
  204. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/Empty.vue +20 -0
  205. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyContent.vue +20 -0
  206. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyDescription.vue +20 -0
  207. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyHeader.vue +20 -0
  208. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyMedia.vue +21 -0
  209. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyTitle.vue +17 -0
  210. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/index.ts +26 -0
  211. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/Field.vue +25 -0
  212. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldContent.vue +20 -0
  213. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldDescription.vue +22 -0
  214. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldError.vue +53 -0
  215. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldGroup.vue +20 -0
  216. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldLabel.vue +23 -0
  217. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldLegend.vue +24 -0
  218. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldSeparator.vue +29 -0
  219. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldSet.vue +21 -0
  220. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldTitle.vue +20 -0
  221. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/index.ts +39 -0
  222. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input/Input.vue +33 -0
  223. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input/index.ts +1 -0
  224. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroup.vue +35 -0
  225. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupAddon.vue +36 -0
  226. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupButton.vue +29 -0
  227. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupInput.vue +19 -0
  228. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupText.vue +19 -0
  229. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupTextarea.vue +19 -0
  230. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/index.ts +51 -0
  231. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/label/Label.vue +26 -0
  232. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/label/index.ts +1 -0
  233. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/Pagination.vue +26 -0
  234. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationContent.vue +22 -0
  235. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationEllipsis.vue +25 -0
  236. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationFirst.vue +33 -0
  237. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationItem.vue +34 -0
  238. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationLast.vue +33 -0
  239. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationNext.vue +33 -0
  240. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationPrevious.vue +33 -0
  241. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/index.ts +8 -0
  242. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/Popover.vue +19 -0
  243. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverAnchor.vue +15 -0
  244. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverContent.vue +45 -0
  245. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverTrigger.vue +15 -0
  246. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/index.ts +4 -0
  247. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendar.vue +62 -0
  248. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarCell.vue +23 -0
  249. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarCellTrigger.vue +41 -0
  250. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGrid.vue +23 -0
  251. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridBody.vue +15 -0
  252. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridHead.vue +15 -0
  253. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridRow.vue +22 -0
  254. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeadCell.vue +23 -0
  255. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeader.vue +23 -0
  256. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeading.vue +30 -0
  257. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarNextButton.vue +32 -0
  258. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarPrevButton.vue +32 -0
  259. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/index.ts +12 -0
  260. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/Select.vue +19 -0
  261. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectContent.vue +51 -0
  262. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectGroup.vue +15 -0
  263. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectItem.vue +44 -0
  264. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectItemText.vue +15 -0
  265. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectLabel.vue +17 -0
  266. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectScrollDownButton.vue +26 -0
  267. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectScrollUpButton.vue +26 -0
  268. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectSeparator.vue +19 -0
  269. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectTrigger.vue +33 -0
  270. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectValue.vue +15 -0
  271. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/index.ts +11 -0
  272. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/separator/Separator.vue +29 -0
  273. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/separator/index.ts +1 -0
  274. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/Sheet.vue +19 -0
  275. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetClose.vue +15 -0
  276. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetContent.vue +62 -0
  277. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetDescription.vue +21 -0
  278. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetFooter.vue +16 -0
  279. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetHeader.vue +15 -0
  280. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetOverlay.vue +21 -0
  281. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetTitle.vue +21 -0
  282. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetTrigger.vue +15 -0
  283. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/index.ts +8 -0
  284. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/skeleton/Skeleton.vue +17 -0
  285. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/skeleton/index.ts +1 -0
  286. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/spinner/Spinner.vue +17 -0
  287. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/spinner/index.ts +1 -0
  288. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/Table.vue +16 -0
  289. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableBody.vue +17 -0
  290. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableCaption.vue +17 -0
  291. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableCell.vue +22 -0
  292. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableEmpty.vue +34 -0
  293. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableFooter.vue +17 -0
  294. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableHead.vue +17 -0
  295. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableHeader.vue +17 -0
  296. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableRow.vue +17 -0
  297. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/index.ts +9 -0
  298. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/Tabs.vue +24 -0
  299. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsContent.vue +21 -0
  300. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsList.vue +24 -0
  301. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsTrigger.vue +26 -0
  302. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/index.ts +4 -0
  303. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/textarea/Textarea.vue +28 -0
  304. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/textarea/index.ts +1 -0
  305. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/Tooltip.vue +19 -0
  306. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipContent.vue +34 -0
  307. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipProvider.vue +14 -0
  308. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipTrigger.vue +15 -0
  309. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/index.ts +4 -0
  310. package/template/.agents/skills/yss-prototype-stage/assets/shadcn-vue-authoring/utils.ts +7 -0
  311. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/Analysis.vue +16 -0
  312. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/Approval.vue +14 -0
  313. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/CombinedQuery.vue +17 -0
  314. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/ComponentStates.vue +41 -0
  315. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/Conflict.vue +33 -0
  316. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/DateRange.vue +29 -0
  317. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/Frame.vue +7 -0
  318. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/ListDetail.vue +47 -0
  319. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/MultiStep.vue +24 -0
  320. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/Notice.vue +5 -0
  321. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/OwnerValidity.vue +26 -0
  322. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/SearchSelect.vue +32 -0
  323. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/Workspace.vue +174 -0
  324. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/analysis-standard.config.json +6 -0
  325. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/analysis-standard.ts +3 -0
  326. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/analysis.scenarios.json +276 -0
  327. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/approval-standard.config.json +6 -0
  328. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/approval-standard.ts +3 -0
  329. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/approval.scenarios.json +207 -0
  330. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/business-controls.css +14 -0
  331. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/business-controls.js +24 -0
  332. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query-standard.config.json +6 -0
  333. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query-standard.ts +3 -0
  334. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query.scenarios.json +298 -0
  335. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/component-states-standard.config.json +6 -0
  336. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/component-states-standard.ts +3 -0
  337. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/conflict-standard.config.json +6 -0
  338. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/conflict-standard.ts +3 -0
  339. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/conflict.scenarios.json +229 -0
  340. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-glass.config.json +6 -0
  341. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-glass.ts +3 -0
  342. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-standard.config.json +6 -0
  343. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-standard.ts +3 -0
  344. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail.scenarios.json +185 -0
  345. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/mount.ts +4 -0
  346. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-glass.config.json +6 -0
  347. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-glass.ts +3 -0
  348. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-standard.config.json +6 -0
  349. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-standard.ts +3 -0
  350. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step.scenarios.json +188 -0
  351. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity-standard.config.json +6 -0
  352. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity-standard.ts +3 -0
  353. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity.scenarios.json +298 -0
  354. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/patterns.css +26 -0
  355. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/refinement.css +129 -0
  356. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workbench.ts +1 -0
  357. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-definition.ts +40 -0
  358. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-glass.config.json +6 -0
  359. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-glass.ts +3 -0
  360. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-model.js +75 -0
  361. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-page.ts +18 -0
  362. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-standard.config.json +6 -0
  363. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-standard.ts +3 -0
  364. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.css +101 -0
  365. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.scenarios.json +2015 -0
  366. package/template/.agents/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.ts +26 -0
  367. package/template/.agents/skills/yss-prototype-stage/references/business-patterns.md +42 -0
  368. package/template/.agents/skills/yss-prototype-stage/references/comparison-tool.md +48 -0
  369. package/template/.agents/skills/yss-prototype-stage/references/component-recipes.md +41 -0
  370. package/template/.agents/skills/yss-prototype-stage/references/concept-comparison.md +26 -0
  371. package/template/.agents/skills/yss-prototype-stage/references/enterprise-workspace.md +53 -0
  372. package/template/.agents/skills/yss-prototype-stage/references/low-fidelity-exercise.md +32 -0
  373. package/template/.agents/skills/yss-prototype-stage/references/product-design-adapter.md +11 -5
  374. package/template/.agents/skills/yss-prototype-stage/references/prototype-profile-routing.md +10 -6
  375. package/template/.agents/skills/yss-prototype-stage/references/prototype-verification.md +25 -0
  376. package/template/.agents/skills/yss-prototype-stage/references/resource-lifecycle.md +20 -0
  377. package/template/.agents/skills/yss-prototype-stage/references/search-date-patterns.md +28 -0
  378. package/template/.agents/skills/yss-prototype-stage/references/shadcn-integration.md +5 -0
  379. package/template/.agents/skills/yss-prototype-stage/references/shadcn-vue-integration.md +46 -0
  380. package/template/.agents/skills/yss-prototype-stage/references/usability-research.md +26 -0
  381. package/template/.agents/skills/yss-prototype-stage/scripts/browser-session.mjs +57 -0
  382. package/template/.agents/skills/yss-prototype-stage/scripts/build-shadcn-vue-prototype.mjs +137 -0
  383. package/template/.agents/skills/yss-prototype-stage/scripts/compose-workspace-scenarios.mjs +22 -0
  384. package/template/.agents/skills/yss-prototype-stage/scripts/export-business-patterns.mjs +7 -0
  385. package/template/.agents/skills/yss-prototype-stage/scripts/export-low-fidelity-exercise.mjs +18 -0
  386. package/template/.agents/skills/yss-prototype-stage/scripts/export-vue-patterns.mjs +21 -0
  387. package/template/.agents/skills/yss-prototype-stage/scripts/offline-html.mjs +60 -23
  388. package/template/.agents/skills/yss-prototype-stage/scripts/prototype-comparison.mjs +208 -0
  389. package/template/.agents/skills/yss-prototype-stage/scripts/prototype-contract.mjs +19 -14
  390. package/template/.agents/skills/yss-prototype-stage/scripts/scenario-contract.mjs +31 -0
  391. package/template/.agents/skills/yss-prototype-stage/scripts/verify-prototype-design.mjs +97 -0
  392. package/template/.agents/skills/yss-prototype-stage/tests/antd-reference.test.mjs +4 -24
  393. package/template/.agents/skills/yss-prototype-stage/tests/browser-harness.mjs +37 -0
  394. package/template/.agents/skills/yss-prototype-stage/tests/browser-visual.mjs +22 -0
  395. package/template/.agents/skills/yss-prototype-stage/tests/business-controls-browser.mjs +43 -0
  396. package/template/.agents/skills/yss-prototype-stage/tests/business-controls.test.mjs +20 -0
  397. package/template/.agents/skills/yss-prototype-stage/tests/compact-theme-browser.mjs +53 -0
  398. package/template/.agents/skills/yss-prototype-stage/tests/comparison-browser-smoke.mjs +77 -0
  399. package/template/.agents/skills/yss-prototype-stage/tests/comparison-fixture.mjs +16 -0
  400. package/template/.agents/skills/yss-prototype-stage/tests/comparison.test.mjs +46 -0
  401. package/template/.agents/skills/yss-prototype-stage/tests/components-browser.mjs +60 -0
  402. package/template/.agents/skills/yss-prototype-stage/tests/patterns-browser.mjs +84 -0
  403. package/template/.agents/skills/yss-prototype-stage/tests/reliability.test.mjs +34 -0
  404. package/template/.agents/skills/yss-prototype-stage/tests/retirement.test.mjs +8 -0
  405. package/template/.agents/skills/yss-prototype-stage/tests/run-scenarios.mjs +19 -2
  406. package/template/.agents/skills/yss-prototype-stage/tests/shadcn-vue.test.mjs +43 -0
  407. package/template/.agents/skills/yss-prototype-stage/tests/verification-entry.test.mjs +16 -0
  408. package/template/.agents/skills/yss-prototype-stage/tests/workbench-smoke.mjs +36 -21
  409. package/template/.agents/skills/yss-prototype-stage/tests/workspace-browser.mjs +50 -0
  410. package/template/.agents/skills/yss-prototype-stage/tests/workspace.test.mjs +70 -0
  411. package/template/.agents/skills/yss-prototype-stage/tests/zoom-browser.mjs +26 -0
  412. package/template/.agents/skills/yss-research/SKILL.md +4 -0
  413. package/template/.agents/skills/yss-stage-decision/SKILL.md +2 -0
  414. package/template/.agents/skills/yss-technical-design/SKILL.md +4 -0
  415. package/template/.agents/skills/yss-ui-business-page-generation/SKILL.md +4 -61
  416. package/template/.agents/skills/yss-ui-business-page-generation/references/page-composition-example.md +50 -0
  417. package/template/.agents/skills/yss-ui-business-page-generation/references/page-layout-example.md +19 -0
  418. package/template/.agents/skills/ytable-usage/SKILL.md +3 -191
  419. package/template/.agents/skills/ytable-usage/references/selection-and-batch.md +30 -0
  420. package/template/.agents/skills/ytable-usage/references/table-pagination-examples.md +170 -0
  421. package/template/.codex/skills/archify/SKILL.md +4 -52
  422. package/template/.codex/skills/archify/references/authoring-notes.md +12 -0
  423. package/template/.codex/skills/archify/references/authoring-workflow.md +25 -0
  424. package/template/.codex/skills/archify/references/delivery-workflow.md +25 -0
  425. package/template/.codex/skills/archify/references/upstream-updates.md +12 -0
  426. package/template/.codex/skills/code-review/SKILL.md +3 -34
  427. package/template/.codex/skills/code-review/references/legacy-convergence.md +5 -0
  428. package/template/.codex/skills/code-review/references/review-axis-checklists.md +18 -0
  429. package/template/.codex/skills/code-review/references/smell-baseline.md +23 -0
  430. package/template/.codex/skills/codebase-design/SKILL.md +4 -0
  431. package/template/.codex/skills/codebase-design/references/architecture-audit.md +69 -0
  432. package/template/.codex/skills/diagnosing-bugs/SKILL.md +3 -91
  433. package/template/.codex/skills/diagnosing-bugs/references/feedback-loop.md +53 -0
  434. package/template/.codex/skills/diagnosing-bugs/references/investigation.md +49 -0
  435. package/template/.codex/skills/frontend-commit/SKILL.md +4 -93
  436. package/template/.codex/skills/git-commit-core/SKILL.md +18 -0
  437. package/template/.codex/skills/git-commit-core/agents/openai.yaml +2 -0
  438. package/template/.codex/skills/java-backend-commit/SKILL.md +4 -96
  439. package/template/.codex/skills/llm-wiki/SKILL.md +12 -13
  440. package/template/.codex/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
  441. package/template/.codex/skills/llm-wiki/references/compile.md +21 -114
  442. package/template/.codex/skills/llm-wiki/references/ingest.md +8 -33
  443. package/template/.codex/skills/llm-wiki/references/lint.md +9 -46
  444. package/template/.codex/skills/llm-wiki/references/query.md +9 -18
  445. package/template/.codex/skills/llm-wiki/references/schema.md +56 -29
  446. package/template/.codex/skills/llm-wiki/references/transactions.md +48 -0
  447. package/template/.codex/skills/llm-wiki/references/writing.md +4 -4
  448. package/template/.codex/skills/llm-wiki/scripts/advise.mjs +46 -58
  449. package/template/.codex/skills/llm-wiki/scripts/advise.test.mjs +11 -16
  450. package/template/.codex/skills/llm-wiki/scripts/core.mjs +262 -0
  451. package/template/.codex/skills/llm-wiki/scripts/extract.mjs +35 -18
  452. package/template/.codex/skills/llm-wiki/scripts/extract.test.mjs +5 -8
  453. package/template/.codex/skills/llm-wiki/scripts/feedback.mjs +51 -0
  454. package/template/.codex/skills/llm-wiki/scripts/inventory.mjs +43 -171
  455. package/template/.codex/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
  456. package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
  457. package/template/.codex/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
  458. package/template/.codex/skills/llm-wiki/scripts/migrate.mjs +51 -0
  459. package/template/.codex/skills/llm-wiki/scripts/query.mjs +149 -0
  460. package/template/.codex/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
  461. package/template/.codex/skills/llm-wiki/scripts/sources.mjs +166 -0
  462. package/template/.codex/skills/llm-wiki/scripts/transaction.mjs +384 -0
  463. package/template/.codex/skills/llm-wiki/scripts/v2.test.mjs +354 -0
  464. package/template/.codex/skills/maintaining-skills/references/authoring.md +6 -0
  465. package/template/.codex/skills/prototype/LOGIC.md +1 -1
  466. package/template/.codex/skills/prototype/SKILL.md +5 -19
  467. package/template/.codex/skills/prototype-review/SKILL.md +11 -0
  468. package/template/.codex/skills/prototype-review/references/component-qa.md +32 -0
  469. package/template/.codex/skills/setup-matt-pocock-skills/SKILL.md +4 -74
  470. package/template/.codex/skills/setup-matt-pocock-skills/references/configuration-decisions.md +42 -0
  471. package/template/.codex/skills/setup-matt-pocock-skills/references/write-configuration.md +42 -0
  472. package/template/.codex/skills/to-spec/SKILL.md +9 -62
  473. package/template/.codex/skills/to-tickets/SKILL.md +20 -86
  474. package/template/.codex/skills/using-git-worktrees/SKILL.md +5 -122
  475. package/template/.codex/skills/using-git-worktrees/references/git-fallback.md +46 -0
  476. package/template/.codex/skills/using-git-worktrees/references/setup-and-baseline.md +45 -0
  477. package/template/.codex/skills/using-git-worktrees/references/troubleshooting.md +47 -0
  478. package/template/.codex/skills/wayfinder/SKILL.md +7 -86
  479. package/template/.codex/skills/wayfinder/references/chart-map.md +14 -0
  480. package/template/.codex/skills/wayfinder/references/map-format.md +49 -0
  481. package/template/.codex/skills/wayfinder/references/scope-and-frontier.md +24 -0
  482. package/template/.codex/skills/wayfinder/references/ticket-types.md +12 -0
  483. package/template/.codex/skills/wayfinder/references/work-map.md +15 -0
  484. package/template/.codex/skills/writing-for-agents/SKILL-MECHANICS.md +20 -11
  485. package/template/.codex/skills/yedit-table-usage/SKILL.md +5 -172
  486. package/template/.codex/skills/yedit-table-usage/references/editable-table-example.md +141 -0
  487. package/template/.codex/skills/yedit-table-usage/references/select-and-filter-examples.md +38 -0
  488. package/template/.codex/skills/yss-ddd-scaffold-generator/SKILL.md +4 -25
  489. package/template/.codex/skills/yss-ddd-scaffold-generator/references/engineering-checks.md +11 -0
  490. package/template/.codex/skills/yss-ddd-scaffold-generator/references/generation-workflow.md +14 -0
  491. package/template/.codex/skills/yss-ddd-scaffold-generator/references/platform-selection.md +16 -0
  492. package/template/.codex/skills/yss-design-system/SKILL.md +13 -3
  493. package/template/.codex/skills/yss-design-system/assets/enterprise-craft/app.js +53 -0
  494. package/template/.codex/skills/yss-design-system/assets/enterprise-craft/index.html +2 -0
  495. package/template/.codex/skills/yss-design-system/assets/enterprise-craft/scenarios.js +14 -0
  496. package/template/.codex/skills/yss-design-system/assets/enterprise-craft/styles.css +32 -0
  497. package/template/.codex/skills/yss-design-system/references/data-quality-theme.md +2 -2
  498. package/template/.codex/skills/yss-design-system/references/design-qa-theme.md +1 -1
  499. package/template/.codex/skills/yss-design-system/references/design-system.md +3 -3
  500. package/template/.codex/skills/yss-design-system/references/enterprise-craft.md +33 -0
  501. package/template/.codex/skills/yss-design-system/references/page-composition.md +24 -0
  502. package/template/.codex/skills/yss-design-system/references/prototype-default-theme.md +26 -0
  503. package/template/.codex/skills/yss-design-system/references/search-date-theme.md +19 -0
  504. package/template/.codex/skills/yss-design-system/scripts/export-craft-examples.mjs +30 -0
  505. package/template/.codex/skills/yss-hook/SKILL.md +8 -102
  506. package/template/.codex/skills/yss-hook/references/async-actions.md +49 -0
  507. package/template/.codex/skills/yss-hook/references/list-pagination.md +46 -0
  508. package/template/.codex/skills/yss-hook/references/polling.md +20 -0
  509. package/template/.codex/skills/yss-implementation-contract-compiler/SKILL.md +8 -3
  510. package/template/.codex/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
  511. package/template/.codex/skills/yss-implementation-contract-compiler/references/scaffold-compilation.md +7 -0
  512. package/template/.codex/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
  513. package/template/.codex/skills/yss-openapi-draft-review/SKILL.md +2 -49
  514. package/template/.codex/skills/yss-openapi-draft-review/references/review-output.md +45 -0
  515. package/template/.codex/skills/yss-openapi-draft-review/references/semantic-review.md +16 -0
  516. package/template/.codex/skills/yss-openapi-governance/SKILL.md +2 -48
  517. package/template/.codex/skills/yss-openapi-governance/references/governance-workflow.md +38 -0
  518. package/template/.codex/skills/yss-openapi-governance/references/locked-toolchain.md +22 -0
  519. package/template/.codex/skills/yss-product-lifecycle/SKILL.md +24 -20
  520. package/template/.codex/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
  521. package/template/.codex/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
  522. package/template/.codex/skills/yss-product-lifecycle/references/orchestration-contract.yaml +429 -384
  523. package/template/.codex/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  524. package/template/.codex/skills/yss-product-lifecycle/references/plan-requirements.md +12 -0
  525. package/template/.codex/skills/yss-product-lifecycle/references/state-model.md +3 -3
  526. package/template/.codex/skills/yss-prototype-stage/SKILL.md +27 -8
  527. package/template/.codex/skills/yss-prototype-stage/assets/comparison/comparison.css +12 -0
  528. package/template/.codex/skills/yss-prototype-stage/assets/comparison/comparison.js +52 -0
  529. package/template/.codex/skills/yss-prototype-stage/assets/comparison/index.html +6 -0
  530. package/template/.codex/skills/yss-prototype-stage/assets/comparison/review-ready.js +2 -0
  531. package/template/.codex/skills/yss-prototype-stage/assets/low-fidelity-exercise/app.js +17 -0
  532. package/template/.codex/skills/yss-prototype-stage/assets/low-fidelity-exercise/index.html +1 -0
  533. package/template/.codex/skills/yss-prototype-stage/assets/low-fidelity-exercise/styles.css +1 -0
  534. package/template/.codex/skills/yss-prototype-stage/assets/native-workbench/app.js +12 -6
  535. package/template/.codex/skills/yss-prototype-stage/assets/native-workbench/index.html +1 -1
  536. package/template/.codex/skills/yss-prototype-stage/assets/native-workbench/scenarios.json +297 -0
  537. package/template/.codex/skills/yss-prototype-stage/assets/native-workbench/styles.css +2 -0
  538. package/template/.codex/skills/yss-prototype-stage/assets/offline-html/app.js +7 -5
  539. package/template/.codex/skills/yss-prototype-stage/assets/offline-html/scenarios.json +297 -0
  540. package/template/.codex/skills/yss-prototype-stage/assets/prototype-theme.css +92 -0
  541. package/template/.codex/skills/yss-prototype-stage/assets/scenario-runtime.js +22 -0
  542. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/SHADCN-LICENSE.txt +21 -0
  543. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/package.json +23 -0
  544. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/pnpm-lock.yaml +1278 -0
  545. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/registry-manifest.json +936 -0
  546. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/theme.css +107 -0
  547. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/Alert.vue +21 -0
  548. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/AlertDescription.vue +17 -0
  549. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/AlertTitle.vue +17 -0
  550. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/index.ts +24 -0
  551. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialog.vue +15 -0
  552. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogAction.vue +18 -0
  553. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogCancel.vue +25 -0
  554. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogContent.vue +44 -0
  555. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogDescription.vue +23 -0
  556. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogFooter.vue +22 -0
  557. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogHeader.vue +17 -0
  558. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogTitle.vue +21 -0
  559. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
  560. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/index.ts +9 -0
  561. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/badge/Badge.vue +26 -0
  562. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/badge/index.ts +26 -0
  563. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/Breadcrumb.vue +17 -0
  564. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbEllipsis.vue +23 -0
  565. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbItem.vue +17 -0
  566. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbLink.vue +21 -0
  567. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbList.vue +17 -0
  568. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbPage.vue +20 -0
  569. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbSeparator.vue +22 -0
  570. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/index.ts +7 -0
  571. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/button/Button.vue +31 -0
  572. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/button/index.ts +40 -0
  573. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/Card.vue +22 -0
  574. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardAction.vue +17 -0
  575. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardContent.vue +17 -0
  576. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardDescription.vue +17 -0
  577. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardFooter.vue +17 -0
  578. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardHeader.vue +17 -0
  579. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardTitle.vue +17 -0
  580. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/index.ts +7 -0
  581. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/checkbox/Checkbox.vue +35 -0
  582. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/checkbox/index.ts +1 -0
  583. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/Combobox.vue +19 -0
  584. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxAnchor.vue +23 -0
  585. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxEmpty.vue +21 -0
  586. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxGroup.vue +27 -0
  587. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxInput.vue +42 -0
  588. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxItem.vue +24 -0
  589. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxItemIndicator.vue +23 -0
  590. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxList.vue +33 -0
  591. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxSeparator.vue +21 -0
  592. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxTrigger.vue +24 -0
  593. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxViewport.vue +23 -0
  594. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/index.ts +13 -0
  595. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/Dialog.vue +19 -0
  596. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogClose.vue +15 -0
  597. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogContent.vue +53 -0
  598. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogDescription.vue +23 -0
  599. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogFooter.vue +27 -0
  600. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogHeader.vue +17 -0
  601. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogOverlay.vue +21 -0
  602. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogScrollContent.vue +59 -0
  603. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogTitle.vue +23 -0
  604. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogTrigger.vue +15 -0
  605. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/index.ts +10 -0
  606. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenu.vue +19 -0
  607. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
  608. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
  609. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuGroup.vue +15 -0
  610. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuItem.vue +31 -0
  611. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
  612. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  613. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  614. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  615. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  616. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
  617. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
  618. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  619. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  620. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/index.ts +16 -0
  621. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/Empty.vue +20 -0
  622. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyContent.vue +20 -0
  623. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyDescription.vue +20 -0
  624. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyHeader.vue +20 -0
  625. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyMedia.vue +21 -0
  626. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyTitle.vue +17 -0
  627. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/index.ts +26 -0
  628. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/Field.vue +25 -0
  629. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldContent.vue +20 -0
  630. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldDescription.vue +22 -0
  631. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldError.vue +53 -0
  632. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldGroup.vue +20 -0
  633. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldLabel.vue +23 -0
  634. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldLegend.vue +24 -0
  635. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldSeparator.vue +29 -0
  636. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldSet.vue +21 -0
  637. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldTitle.vue +20 -0
  638. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/index.ts +39 -0
  639. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input/Input.vue +33 -0
  640. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input/index.ts +1 -0
  641. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroup.vue +35 -0
  642. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupAddon.vue +36 -0
  643. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupButton.vue +29 -0
  644. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupInput.vue +19 -0
  645. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupText.vue +19 -0
  646. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupTextarea.vue +19 -0
  647. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/index.ts +51 -0
  648. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/label/Label.vue +26 -0
  649. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/label/index.ts +1 -0
  650. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/Pagination.vue +26 -0
  651. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationContent.vue +22 -0
  652. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationEllipsis.vue +25 -0
  653. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationFirst.vue +33 -0
  654. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationItem.vue +34 -0
  655. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationLast.vue +33 -0
  656. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationNext.vue +33 -0
  657. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationPrevious.vue +33 -0
  658. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/index.ts +8 -0
  659. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/Popover.vue +19 -0
  660. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverAnchor.vue +15 -0
  661. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverContent.vue +45 -0
  662. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverTrigger.vue +15 -0
  663. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/index.ts +4 -0
  664. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendar.vue +62 -0
  665. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarCell.vue +23 -0
  666. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarCellTrigger.vue +41 -0
  667. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGrid.vue +23 -0
  668. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridBody.vue +15 -0
  669. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridHead.vue +15 -0
  670. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridRow.vue +22 -0
  671. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeadCell.vue +23 -0
  672. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeader.vue +23 -0
  673. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeading.vue +30 -0
  674. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarNextButton.vue +32 -0
  675. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarPrevButton.vue +32 -0
  676. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/index.ts +12 -0
  677. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/Select.vue +19 -0
  678. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectContent.vue +51 -0
  679. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectGroup.vue +15 -0
  680. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectItem.vue +44 -0
  681. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectItemText.vue +15 -0
  682. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectLabel.vue +17 -0
  683. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectScrollDownButton.vue +26 -0
  684. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectScrollUpButton.vue +26 -0
  685. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectSeparator.vue +19 -0
  686. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectTrigger.vue +33 -0
  687. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectValue.vue +15 -0
  688. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/index.ts +11 -0
  689. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/separator/Separator.vue +29 -0
  690. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/separator/index.ts +1 -0
  691. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/Sheet.vue +19 -0
  692. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetClose.vue +15 -0
  693. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetContent.vue +62 -0
  694. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetDescription.vue +21 -0
  695. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetFooter.vue +16 -0
  696. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetHeader.vue +15 -0
  697. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetOverlay.vue +21 -0
  698. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetTitle.vue +21 -0
  699. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetTrigger.vue +15 -0
  700. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/index.ts +8 -0
  701. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/skeleton/Skeleton.vue +17 -0
  702. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/skeleton/index.ts +1 -0
  703. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/spinner/Spinner.vue +17 -0
  704. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/spinner/index.ts +1 -0
  705. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/Table.vue +16 -0
  706. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableBody.vue +17 -0
  707. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableCaption.vue +17 -0
  708. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableCell.vue +22 -0
  709. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableEmpty.vue +34 -0
  710. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableFooter.vue +17 -0
  711. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableHead.vue +17 -0
  712. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableHeader.vue +17 -0
  713. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableRow.vue +17 -0
  714. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/index.ts +9 -0
  715. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/Tabs.vue +24 -0
  716. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsContent.vue +21 -0
  717. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsList.vue +24 -0
  718. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsTrigger.vue +26 -0
  719. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/index.ts +4 -0
  720. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/textarea/Textarea.vue +28 -0
  721. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/textarea/index.ts +1 -0
  722. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/Tooltip.vue +19 -0
  723. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipContent.vue +34 -0
  724. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipProvider.vue +14 -0
  725. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipTrigger.vue +15 -0
  726. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/index.ts +4 -0
  727. package/template/.codex/skills/yss-prototype-stage/assets/shadcn-vue-authoring/utils.ts +7 -0
  728. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/Analysis.vue +16 -0
  729. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/Approval.vue +14 -0
  730. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/CombinedQuery.vue +17 -0
  731. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/ComponentStates.vue +41 -0
  732. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/Conflict.vue +33 -0
  733. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/DateRange.vue +29 -0
  734. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/Frame.vue +7 -0
  735. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/ListDetail.vue +47 -0
  736. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/MultiStep.vue +24 -0
  737. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/Notice.vue +5 -0
  738. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/OwnerValidity.vue +26 -0
  739. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/SearchSelect.vue +32 -0
  740. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/Workspace.vue +174 -0
  741. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/analysis-standard.config.json +6 -0
  742. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/analysis-standard.ts +3 -0
  743. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/analysis.scenarios.json +276 -0
  744. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/approval-standard.config.json +6 -0
  745. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/approval-standard.ts +3 -0
  746. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/approval.scenarios.json +207 -0
  747. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/business-controls.css +14 -0
  748. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/business-controls.js +24 -0
  749. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query-standard.config.json +6 -0
  750. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query-standard.ts +3 -0
  751. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query.scenarios.json +298 -0
  752. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/component-states-standard.config.json +6 -0
  753. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/component-states-standard.ts +3 -0
  754. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/conflict-standard.config.json +6 -0
  755. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/conflict-standard.ts +3 -0
  756. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/conflict.scenarios.json +229 -0
  757. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-glass.config.json +6 -0
  758. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-glass.ts +3 -0
  759. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-standard.config.json +6 -0
  760. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-standard.ts +3 -0
  761. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail.scenarios.json +185 -0
  762. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/mount.ts +4 -0
  763. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-glass.config.json +6 -0
  764. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-glass.ts +3 -0
  765. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-standard.config.json +6 -0
  766. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-standard.ts +3 -0
  767. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step.scenarios.json +188 -0
  768. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity-standard.config.json +6 -0
  769. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity-standard.ts +3 -0
  770. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity.scenarios.json +298 -0
  771. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/patterns.css +26 -0
  772. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/refinement.css +129 -0
  773. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workbench.ts +1 -0
  774. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-definition.ts +40 -0
  775. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-glass.config.json +6 -0
  776. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-glass.ts +3 -0
  777. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-model.js +75 -0
  778. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-page.ts +18 -0
  779. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-standard.config.json +6 -0
  780. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-standard.ts +3 -0
  781. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.css +101 -0
  782. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.scenarios.json +2015 -0
  783. package/template/.codex/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.ts +26 -0
  784. package/template/.codex/skills/yss-prototype-stage/references/business-patterns.md +42 -0
  785. package/template/.codex/skills/yss-prototype-stage/references/comparison-tool.md +48 -0
  786. package/template/.codex/skills/yss-prototype-stage/references/component-recipes.md +41 -0
  787. package/template/.codex/skills/yss-prototype-stage/references/concept-comparison.md +26 -0
  788. package/template/.codex/skills/yss-prototype-stage/references/enterprise-workspace.md +53 -0
  789. package/template/.codex/skills/yss-prototype-stage/references/low-fidelity-exercise.md +32 -0
  790. package/template/.codex/skills/yss-prototype-stage/references/product-design-adapter.md +11 -5
  791. package/template/.codex/skills/yss-prototype-stage/references/prototype-profile-routing.md +10 -6
  792. package/template/.codex/skills/yss-prototype-stage/references/prototype-verification.md +25 -0
  793. package/template/.codex/skills/yss-prototype-stage/references/resource-lifecycle.md +20 -0
  794. package/template/.codex/skills/yss-prototype-stage/references/search-date-patterns.md +28 -0
  795. package/template/.codex/skills/yss-prototype-stage/references/shadcn-integration.md +5 -0
  796. package/template/.codex/skills/yss-prototype-stage/references/shadcn-vue-integration.md +46 -0
  797. package/template/.codex/skills/yss-prototype-stage/references/usability-research.md +26 -0
  798. package/template/.codex/skills/yss-prototype-stage/scripts/browser-session.mjs +57 -0
  799. package/template/.codex/skills/yss-prototype-stage/scripts/build-shadcn-vue-prototype.mjs +137 -0
  800. package/template/.codex/skills/yss-prototype-stage/scripts/compose-workspace-scenarios.mjs +22 -0
  801. package/template/.codex/skills/yss-prototype-stage/scripts/export-business-patterns.mjs +7 -0
  802. package/template/.codex/skills/yss-prototype-stage/scripts/export-low-fidelity-exercise.mjs +18 -0
  803. package/template/.codex/skills/yss-prototype-stage/scripts/export-vue-patterns.mjs +21 -0
  804. package/template/.codex/skills/yss-prototype-stage/scripts/offline-html.mjs +60 -23
  805. package/template/.codex/skills/yss-prototype-stage/scripts/prototype-comparison.mjs +208 -0
  806. package/template/.codex/skills/yss-prototype-stage/scripts/prototype-contract.mjs +19 -14
  807. package/template/.codex/skills/yss-prototype-stage/scripts/scenario-contract.mjs +31 -0
  808. package/template/.codex/skills/yss-prototype-stage/scripts/verify-prototype-design.mjs +97 -0
  809. package/template/.codex/skills/yss-prototype-stage/tests/antd-reference.test.mjs +4 -24
  810. package/template/.codex/skills/yss-prototype-stage/tests/browser-harness.mjs +37 -0
  811. package/template/.codex/skills/yss-prototype-stage/tests/browser-visual.mjs +22 -0
  812. package/template/.codex/skills/yss-prototype-stage/tests/business-controls-browser.mjs +43 -0
  813. package/template/.codex/skills/yss-prototype-stage/tests/business-controls.test.mjs +20 -0
  814. package/template/.codex/skills/yss-prototype-stage/tests/compact-theme-browser.mjs +53 -0
  815. package/template/.codex/skills/yss-prototype-stage/tests/comparison-browser-smoke.mjs +77 -0
  816. package/template/.codex/skills/yss-prototype-stage/tests/comparison-fixture.mjs +16 -0
  817. package/template/.codex/skills/yss-prototype-stage/tests/comparison.test.mjs +46 -0
  818. package/template/.codex/skills/yss-prototype-stage/tests/components-browser.mjs +60 -0
  819. package/template/.codex/skills/yss-prototype-stage/tests/patterns-browser.mjs +84 -0
  820. package/template/.codex/skills/yss-prototype-stage/tests/reliability.test.mjs +34 -0
  821. package/template/.codex/skills/yss-prototype-stage/tests/retirement.test.mjs +8 -0
  822. package/template/.codex/skills/yss-prototype-stage/tests/run-scenarios.mjs +19 -2
  823. package/template/.codex/skills/yss-prototype-stage/tests/shadcn-vue.test.mjs +43 -0
  824. package/template/.codex/skills/yss-prototype-stage/tests/verification-entry.test.mjs +16 -0
  825. package/template/.codex/skills/yss-prototype-stage/tests/workbench-smoke.mjs +36 -21
  826. package/template/.codex/skills/yss-prototype-stage/tests/workspace-browser.mjs +50 -0
  827. package/template/.codex/skills/yss-prototype-stage/tests/workspace.test.mjs +70 -0
  828. package/template/.codex/skills/yss-prototype-stage/tests/zoom-browser.mjs +26 -0
  829. package/template/.codex/skills/yss-research/SKILL.md +4 -0
  830. package/template/.codex/skills/yss-stage-decision/SKILL.md +2 -0
  831. package/template/.codex/skills/yss-technical-design/SKILL.md +4 -0
  832. package/template/.codex/skills/yss-ui-business-page-generation/SKILL.md +4 -61
  833. package/template/.codex/skills/yss-ui-business-page-generation/references/page-composition-example.md +50 -0
  834. package/template/.codex/skills/yss-ui-business-page-generation/references/page-layout-example.md +19 -0
  835. package/template/.codex/skills/ytable-usage/SKILL.md +3 -191
  836. package/template/.codex/skills/ytable-usage/references/selection-and-batch.md +30 -0
  837. package/template/.codex/skills/ytable-usage/references/table-pagination-examples.md +170 -0
  838. package/template/.cursor/skills/archify/SKILL.md +4 -52
  839. package/template/.cursor/skills/archify/references/authoring-notes.md +12 -0
  840. package/template/.cursor/skills/archify/references/authoring-workflow.md +25 -0
  841. package/template/.cursor/skills/archify/references/delivery-workflow.md +25 -0
  842. package/template/.cursor/skills/archify/references/upstream-updates.md +12 -0
  843. package/template/.cursor/skills/code-review/SKILL.md +3 -34
  844. package/template/.cursor/skills/code-review/references/legacy-convergence.md +5 -0
  845. package/template/.cursor/skills/code-review/references/review-axis-checklists.md +18 -0
  846. package/template/.cursor/skills/code-review/references/smell-baseline.md +23 -0
  847. package/template/.cursor/skills/codebase-design/SKILL.md +4 -0
  848. package/template/.cursor/skills/codebase-design/references/architecture-audit.md +69 -0
  849. package/template/.cursor/skills/diagnosing-bugs/SKILL.md +3 -91
  850. package/template/.cursor/skills/diagnosing-bugs/references/feedback-loop.md +53 -0
  851. package/template/.cursor/skills/diagnosing-bugs/references/investigation.md +49 -0
  852. package/template/.cursor/skills/frontend-commit/SKILL.md +4 -93
  853. package/template/.cursor/skills/git-commit-core/SKILL.md +18 -0
  854. package/template/.cursor/skills/git-commit-core/agents/openai.yaml +2 -0
  855. package/template/.cursor/skills/java-backend-commit/SKILL.md +4 -96
  856. package/template/.cursor/skills/llm-wiki/SKILL.md +12 -13
  857. package/template/.cursor/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
  858. package/template/.cursor/skills/llm-wiki/references/compile.md +21 -114
  859. package/template/.cursor/skills/llm-wiki/references/ingest.md +8 -33
  860. package/template/.cursor/skills/llm-wiki/references/lint.md +9 -46
  861. package/template/.cursor/skills/llm-wiki/references/query.md +9 -18
  862. package/template/.cursor/skills/llm-wiki/references/schema.md +56 -29
  863. package/template/.cursor/skills/llm-wiki/references/transactions.md +48 -0
  864. package/template/.cursor/skills/llm-wiki/references/writing.md +4 -4
  865. package/template/.cursor/skills/llm-wiki/scripts/advise.mjs +46 -58
  866. package/template/.cursor/skills/llm-wiki/scripts/advise.test.mjs +11 -16
  867. package/template/.cursor/skills/llm-wiki/scripts/core.mjs +262 -0
  868. package/template/.cursor/skills/llm-wiki/scripts/extract.mjs +35 -18
  869. package/template/.cursor/skills/llm-wiki/scripts/extract.test.mjs +5 -8
  870. package/template/.cursor/skills/llm-wiki/scripts/feedback.mjs +51 -0
  871. package/template/.cursor/skills/llm-wiki/scripts/inventory.mjs +43 -171
  872. package/template/.cursor/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
  873. package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
  874. package/template/.cursor/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
  875. package/template/.cursor/skills/llm-wiki/scripts/migrate.mjs +51 -0
  876. package/template/.cursor/skills/llm-wiki/scripts/query.mjs +149 -0
  877. package/template/.cursor/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
  878. package/template/.cursor/skills/llm-wiki/scripts/sources.mjs +166 -0
  879. package/template/.cursor/skills/llm-wiki/scripts/transaction.mjs +384 -0
  880. package/template/.cursor/skills/llm-wiki/scripts/v2.test.mjs +354 -0
  881. package/template/.cursor/skills/maintaining-skills/references/authoring.md +6 -0
  882. package/template/.cursor/skills/prototype/LOGIC.md +1 -1
  883. package/template/.cursor/skills/prototype/SKILL.md +5 -19
  884. package/template/.cursor/skills/prototype-review/SKILL.md +11 -0
  885. package/template/.cursor/skills/prototype-review/references/component-qa.md +32 -0
  886. package/template/.cursor/skills/setup-matt-pocock-skills/SKILL.md +4 -74
  887. package/template/.cursor/skills/setup-matt-pocock-skills/references/configuration-decisions.md +42 -0
  888. package/template/.cursor/skills/setup-matt-pocock-skills/references/write-configuration.md +42 -0
  889. package/template/.cursor/skills/to-spec/SKILL.md +9 -62
  890. package/template/.cursor/skills/to-tickets/SKILL.md +20 -86
  891. package/template/.cursor/skills/using-git-worktrees/SKILL.md +5 -122
  892. package/template/.cursor/skills/using-git-worktrees/references/git-fallback.md +46 -0
  893. package/template/.cursor/skills/using-git-worktrees/references/setup-and-baseline.md +45 -0
  894. package/template/.cursor/skills/using-git-worktrees/references/troubleshooting.md +47 -0
  895. package/template/.cursor/skills/wayfinder/SKILL.md +7 -86
  896. package/template/.cursor/skills/wayfinder/references/chart-map.md +14 -0
  897. package/template/.cursor/skills/wayfinder/references/map-format.md +49 -0
  898. package/template/.cursor/skills/wayfinder/references/scope-and-frontier.md +24 -0
  899. package/template/.cursor/skills/wayfinder/references/ticket-types.md +12 -0
  900. package/template/.cursor/skills/wayfinder/references/work-map.md +15 -0
  901. package/template/.cursor/skills/writing-for-agents/SKILL-MECHANICS.md +20 -11
  902. package/template/.cursor/skills/yedit-table-usage/SKILL.md +5 -172
  903. package/template/.cursor/skills/yedit-table-usage/references/editable-table-example.md +141 -0
  904. package/template/.cursor/skills/yedit-table-usage/references/select-and-filter-examples.md +38 -0
  905. package/template/.cursor/skills/yss-ddd-scaffold-generator/SKILL.md +4 -25
  906. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/engineering-checks.md +11 -0
  907. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/generation-workflow.md +14 -0
  908. package/template/.cursor/skills/yss-ddd-scaffold-generator/references/platform-selection.md +16 -0
  909. package/template/.cursor/skills/yss-design-system/SKILL.md +13 -3
  910. package/template/.cursor/skills/yss-design-system/assets/enterprise-craft/app.js +53 -0
  911. package/template/.cursor/skills/yss-design-system/assets/enterprise-craft/index.html +2 -0
  912. package/template/.cursor/skills/yss-design-system/assets/enterprise-craft/scenarios.js +14 -0
  913. package/template/.cursor/skills/yss-design-system/assets/enterprise-craft/styles.css +32 -0
  914. package/template/.cursor/skills/yss-design-system/references/data-quality-theme.md +2 -2
  915. package/template/.cursor/skills/yss-design-system/references/design-qa-theme.md +1 -1
  916. package/template/.cursor/skills/yss-design-system/references/design-system.md +3 -3
  917. package/template/.cursor/skills/yss-design-system/references/enterprise-craft.md +33 -0
  918. package/template/.cursor/skills/yss-design-system/references/page-composition.md +24 -0
  919. package/template/.cursor/skills/yss-design-system/references/prototype-default-theme.md +26 -0
  920. package/template/.cursor/skills/yss-design-system/references/search-date-theme.md +19 -0
  921. package/template/.cursor/skills/yss-design-system/scripts/export-craft-examples.mjs +30 -0
  922. package/template/.cursor/skills/yss-hook/SKILL.md +8 -102
  923. package/template/.cursor/skills/yss-hook/references/async-actions.md +49 -0
  924. package/template/.cursor/skills/yss-hook/references/list-pagination.md +46 -0
  925. package/template/.cursor/skills/yss-hook/references/polling.md +20 -0
  926. package/template/.cursor/skills/yss-implementation-contract-compiler/SKILL.md +8 -3
  927. package/template/.cursor/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
  928. package/template/.cursor/skills/yss-implementation-contract-compiler/references/scaffold-compilation.md +7 -0
  929. package/template/.cursor/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
  930. package/template/.cursor/skills/yss-openapi-draft-review/SKILL.md +2 -49
  931. package/template/.cursor/skills/yss-openapi-draft-review/references/review-output.md +45 -0
  932. package/template/.cursor/skills/yss-openapi-draft-review/references/semantic-review.md +16 -0
  933. package/template/.cursor/skills/yss-openapi-governance/SKILL.md +2 -48
  934. package/template/.cursor/skills/yss-openapi-governance/references/governance-workflow.md +38 -0
  935. package/template/.cursor/skills/yss-openapi-governance/references/locked-toolchain.md +22 -0
  936. package/template/.cursor/skills/yss-product-lifecycle/SKILL.md +24 -20
  937. package/template/.cursor/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
  938. package/template/.cursor/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
  939. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration-contract.yaml +429 -384
  940. package/template/.cursor/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  941. package/template/.cursor/skills/yss-product-lifecycle/references/plan-requirements.md +12 -0
  942. package/template/.cursor/skills/yss-product-lifecycle/references/state-model.md +3 -3
  943. package/template/.cursor/skills/yss-prototype-stage/SKILL.md +27 -8
  944. package/template/.cursor/skills/yss-prototype-stage/assets/comparison/comparison.css +12 -0
  945. package/template/.cursor/skills/yss-prototype-stage/assets/comparison/comparison.js +52 -0
  946. package/template/.cursor/skills/yss-prototype-stage/assets/comparison/index.html +6 -0
  947. package/template/.cursor/skills/yss-prototype-stage/assets/comparison/review-ready.js +2 -0
  948. package/template/.cursor/skills/yss-prototype-stage/assets/low-fidelity-exercise/app.js +17 -0
  949. package/template/.cursor/skills/yss-prototype-stage/assets/low-fidelity-exercise/index.html +1 -0
  950. package/template/.cursor/skills/yss-prototype-stage/assets/low-fidelity-exercise/styles.css +1 -0
  951. package/template/.cursor/skills/yss-prototype-stage/assets/native-workbench/app.js +12 -6
  952. package/template/.cursor/skills/yss-prototype-stage/assets/native-workbench/index.html +1 -1
  953. package/template/.cursor/skills/yss-prototype-stage/assets/native-workbench/scenarios.json +297 -0
  954. package/template/.cursor/skills/yss-prototype-stage/assets/native-workbench/styles.css +2 -0
  955. package/template/.cursor/skills/yss-prototype-stage/assets/offline-html/app.js +7 -5
  956. package/template/.cursor/skills/yss-prototype-stage/assets/offline-html/scenarios.json +297 -0
  957. package/template/.cursor/skills/yss-prototype-stage/assets/prototype-theme.css +92 -0
  958. package/template/.cursor/skills/yss-prototype-stage/assets/scenario-runtime.js +22 -0
  959. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/SHADCN-LICENSE.txt +21 -0
  960. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/package.json +23 -0
  961. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/pnpm-lock.yaml +1278 -0
  962. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/registry-manifest.json +936 -0
  963. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/theme.css +107 -0
  964. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/Alert.vue +21 -0
  965. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/AlertDescription.vue +17 -0
  966. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/AlertTitle.vue +17 -0
  967. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/index.ts +24 -0
  968. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialog.vue +15 -0
  969. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogAction.vue +18 -0
  970. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogCancel.vue +25 -0
  971. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogContent.vue +44 -0
  972. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogDescription.vue +23 -0
  973. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogFooter.vue +22 -0
  974. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogHeader.vue +17 -0
  975. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogTitle.vue +21 -0
  976. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
  977. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/index.ts +9 -0
  978. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/badge/Badge.vue +26 -0
  979. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/badge/index.ts +26 -0
  980. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/Breadcrumb.vue +17 -0
  981. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbEllipsis.vue +23 -0
  982. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbItem.vue +17 -0
  983. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbLink.vue +21 -0
  984. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbList.vue +17 -0
  985. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbPage.vue +20 -0
  986. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbSeparator.vue +22 -0
  987. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/index.ts +7 -0
  988. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/button/Button.vue +31 -0
  989. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/button/index.ts +40 -0
  990. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/Card.vue +22 -0
  991. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardAction.vue +17 -0
  992. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardContent.vue +17 -0
  993. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardDescription.vue +17 -0
  994. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardFooter.vue +17 -0
  995. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardHeader.vue +17 -0
  996. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardTitle.vue +17 -0
  997. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/index.ts +7 -0
  998. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/checkbox/Checkbox.vue +35 -0
  999. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/checkbox/index.ts +1 -0
  1000. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/Combobox.vue +19 -0
  1001. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxAnchor.vue +23 -0
  1002. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxEmpty.vue +21 -0
  1003. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxGroup.vue +27 -0
  1004. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxInput.vue +42 -0
  1005. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxItem.vue +24 -0
  1006. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxItemIndicator.vue +23 -0
  1007. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxList.vue +33 -0
  1008. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxSeparator.vue +21 -0
  1009. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxTrigger.vue +24 -0
  1010. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxViewport.vue +23 -0
  1011. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/index.ts +13 -0
  1012. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/Dialog.vue +19 -0
  1013. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogClose.vue +15 -0
  1014. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogContent.vue +53 -0
  1015. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogDescription.vue +23 -0
  1016. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogFooter.vue +27 -0
  1017. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogHeader.vue +17 -0
  1018. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogOverlay.vue +21 -0
  1019. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogScrollContent.vue +59 -0
  1020. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogTitle.vue +23 -0
  1021. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogTrigger.vue +15 -0
  1022. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/index.ts +10 -0
  1023. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenu.vue +19 -0
  1024. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
  1025. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
  1026. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuGroup.vue +15 -0
  1027. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuItem.vue +31 -0
  1028. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
  1029. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  1030. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  1031. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  1032. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  1033. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
  1034. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
  1035. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  1036. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  1037. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/index.ts +16 -0
  1038. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/Empty.vue +20 -0
  1039. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyContent.vue +20 -0
  1040. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyDescription.vue +20 -0
  1041. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyHeader.vue +20 -0
  1042. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyMedia.vue +21 -0
  1043. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyTitle.vue +17 -0
  1044. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/index.ts +26 -0
  1045. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/Field.vue +25 -0
  1046. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldContent.vue +20 -0
  1047. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldDescription.vue +22 -0
  1048. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldError.vue +53 -0
  1049. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldGroup.vue +20 -0
  1050. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldLabel.vue +23 -0
  1051. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldLegend.vue +24 -0
  1052. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldSeparator.vue +29 -0
  1053. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldSet.vue +21 -0
  1054. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldTitle.vue +20 -0
  1055. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/index.ts +39 -0
  1056. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input/Input.vue +33 -0
  1057. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input/index.ts +1 -0
  1058. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroup.vue +35 -0
  1059. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupAddon.vue +36 -0
  1060. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupButton.vue +29 -0
  1061. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupInput.vue +19 -0
  1062. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupText.vue +19 -0
  1063. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupTextarea.vue +19 -0
  1064. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/index.ts +51 -0
  1065. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/label/Label.vue +26 -0
  1066. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/label/index.ts +1 -0
  1067. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/Pagination.vue +26 -0
  1068. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationContent.vue +22 -0
  1069. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationEllipsis.vue +25 -0
  1070. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationFirst.vue +33 -0
  1071. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationItem.vue +34 -0
  1072. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationLast.vue +33 -0
  1073. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationNext.vue +33 -0
  1074. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationPrevious.vue +33 -0
  1075. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/index.ts +8 -0
  1076. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/Popover.vue +19 -0
  1077. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverAnchor.vue +15 -0
  1078. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverContent.vue +45 -0
  1079. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverTrigger.vue +15 -0
  1080. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/index.ts +4 -0
  1081. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendar.vue +62 -0
  1082. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarCell.vue +23 -0
  1083. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarCellTrigger.vue +41 -0
  1084. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGrid.vue +23 -0
  1085. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridBody.vue +15 -0
  1086. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridHead.vue +15 -0
  1087. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridRow.vue +22 -0
  1088. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeadCell.vue +23 -0
  1089. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeader.vue +23 -0
  1090. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeading.vue +30 -0
  1091. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarNextButton.vue +32 -0
  1092. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarPrevButton.vue +32 -0
  1093. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/index.ts +12 -0
  1094. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/Select.vue +19 -0
  1095. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectContent.vue +51 -0
  1096. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectGroup.vue +15 -0
  1097. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectItem.vue +44 -0
  1098. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectItemText.vue +15 -0
  1099. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectLabel.vue +17 -0
  1100. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectScrollDownButton.vue +26 -0
  1101. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectScrollUpButton.vue +26 -0
  1102. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectSeparator.vue +19 -0
  1103. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectTrigger.vue +33 -0
  1104. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectValue.vue +15 -0
  1105. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/index.ts +11 -0
  1106. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/separator/Separator.vue +29 -0
  1107. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/separator/index.ts +1 -0
  1108. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/Sheet.vue +19 -0
  1109. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetClose.vue +15 -0
  1110. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetContent.vue +62 -0
  1111. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetDescription.vue +21 -0
  1112. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetFooter.vue +16 -0
  1113. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetHeader.vue +15 -0
  1114. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetOverlay.vue +21 -0
  1115. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetTitle.vue +21 -0
  1116. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetTrigger.vue +15 -0
  1117. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/index.ts +8 -0
  1118. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/skeleton/Skeleton.vue +17 -0
  1119. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/skeleton/index.ts +1 -0
  1120. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/spinner/Spinner.vue +17 -0
  1121. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/spinner/index.ts +1 -0
  1122. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/Table.vue +16 -0
  1123. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableBody.vue +17 -0
  1124. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableCaption.vue +17 -0
  1125. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableCell.vue +22 -0
  1126. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableEmpty.vue +34 -0
  1127. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableFooter.vue +17 -0
  1128. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableHead.vue +17 -0
  1129. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableHeader.vue +17 -0
  1130. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableRow.vue +17 -0
  1131. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/index.ts +9 -0
  1132. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/Tabs.vue +24 -0
  1133. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsContent.vue +21 -0
  1134. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsList.vue +24 -0
  1135. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsTrigger.vue +26 -0
  1136. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/index.ts +4 -0
  1137. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/textarea/Textarea.vue +28 -0
  1138. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/textarea/index.ts +1 -0
  1139. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/Tooltip.vue +19 -0
  1140. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipContent.vue +34 -0
  1141. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipProvider.vue +14 -0
  1142. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipTrigger.vue +15 -0
  1143. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/index.ts +4 -0
  1144. package/template/.cursor/skills/yss-prototype-stage/assets/shadcn-vue-authoring/utils.ts +7 -0
  1145. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/Analysis.vue +16 -0
  1146. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/Approval.vue +14 -0
  1147. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/CombinedQuery.vue +17 -0
  1148. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/ComponentStates.vue +41 -0
  1149. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/Conflict.vue +33 -0
  1150. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/DateRange.vue +29 -0
  1151. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/Frame.vue +7 -0
  1152. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/ListDetail.vue +47 -0
  1153. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/MultiStep.vue +24 -0
  1154. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/Notice.vue +5 -0
  1155. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/OwnerValidity.vue +26 -0
  1156. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/SearchSelect.vue +32 -0
  1157. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/Workspace.vue +174 -0
  1158. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/analysis-standard.config.json +6 -0
  1159. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/analysis-standard.ts +3 -0
  1160. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/analysis.scenarios.json +276 -0
  1161. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/approval-standard.config.json +6 -0
  1162. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/approval-standard.ts +3 -0
  1163. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/approval.scenarios.json +207 -0
  1164. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/business-controls.css +14 -0
  1165. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/business-controls.js +24 -0
  1166. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query-standard.config.json +6 -0
  1167. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query-standard.ts +3 -0
  1168. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query.scenarios.json +298 -0
  1169. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/component-states-standard.config.json +6 -0
  1170. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/component-states-standard.ts +3 -0
  1171. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/conflict-standard.config.json +6 -0
  1172. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/conflict-standard.ts +3 -0
  1173. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/conflict.scenarios.json +229 -0
  1174. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-glass.config.json +6 -0
  1175. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-glass.ts +3 -0
  1176. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-standard.config.json +6 -0
  1177. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-standard.ts +3 -0
  1178. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail.scenarios.json +185 -0
  1179. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/mount.ts +4 -0
  1180. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-glass.config.json +6 -0
  1181. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-glass.ts +3 -0
  1182. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-standard.config.json +6 -0
  1183. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-standard.ts +3 -0
  1184. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step.scenarios.json +188 -0
  1185. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity-standard.config.json +6 -0
  1186. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity-standard.ts +3 -0
  1187. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity.scenarios.json +298 -0
  1188. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/patterns.css +26 -0
  1189. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/refinement.css +129 -0
  1190. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workbench.ts +1 -0
  1191. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-definition.ts +40 -0
  1192. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-glass.config.json +6 -0
  1193. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-glass.ts +3 -0
  1194. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-model.js +75 -0
  1195. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-page.ts +18 -0
  1196. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-standard.config.json +6 -0
  1197. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-standard.ts +3 -0
  1198. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.css +101 -0
  1199. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.scenarios.json +2015 -0
  1200. package/template/.cursor/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.ts +26 -0
  1201. package/template/.cursor/skills/yss-prototype-stage/references/business-patterns.md +42 -0
  1202. package/template/.cursor/skills/yss-prototype-stage/references/comparison-tool.md +48 -0
  1203. package/template/.cursor/skills/yss-prototype-stage/references/component-recipes.md +41 -0
  1204. package/template/.cursor/skills/yss-prototype-stage/references/concept-comparison.md +26 -0
  1205. package/template/.cursor/skills/yss-prototype-stage/references/enterprise-workspace.md +53 -0
  1206. package/template/.cursor/skills/yss-prototype-stage/references/low-fidelity-exercise.md +32 -0
  1207. package/template/.cursor/skills/yss-prototype-stage/references/product-design-adapter.md +11 -5
  1208. package/template/.cursor/skills/yss-prototype-stage/references/prototype-profile-routing.md +10 -6
  1209. package/template/.cursor/skills/yss-prototype-stage/references/prototype-verification.md +25 -0
  1210. package/template/.cursor/skills/yss-prototype-stage/references/resource-lifecycle.md +20 -0
  1211. package/template/.cursor/skills/yss-prototype-stage/references/search-date-patterns.md +28 -0
  1212. package/template/.cursor/skills/yss-prototype-stage/references/shadcn-integration.md +5 -0
  1213. package/template/.cursor/skills/yss-prototype-stage/references/shadcn-vue-integration.md +46 -0
  1214. package/template/.cursor/skills/yss-prototype-stage/references/usability-research.md +26 -0
  1215. package/template/.cursor/skills/yss-prototype-stage/scripts/browser-session.mjs +57 -0
  1216. package/template/.cursor/skills/yss-prototype-stage/scripts/build-shadcn-vue-prototype.mjs +137 -0
  1217. package/template/.cursor/skills/yss-prototype-stage/scripts/compose-workspace-scenarios.mjs +22 -0
  1218. package/template/.cursor/skills/yss-prototype-stage/scripts/export-business-patterns.mjs +7 -0
  1219. package/template/.cursor/skills/yss-prototype-stage/scripts/export-low-fidelity-exercise.mjs +18 -0
  1220. package/template/.cursor/skills/yss-prototype-stage/scripts/export-vue-patterns.mjs +21 -0
  1221. package/template/.cursor/skills/yss-prototype-stage/scripts/offline-html.mjs +60 -23
  1222. package/template/.cursor/skills/yss-prototype-stage/scripts/prototype-comparison.mjs +208 -0
  1223. package/template/.cursor/skills/yss-prototype-stage/scripts/prototype-contract.mjs +19 -14
  1224. package/template/.cursor/skills/yss-prototype-stage/scripts/scenario-contract.mjs +31 -0
  1225. package/template/.cursor/skills/yss-prototype-stage/scripts/verify-prototype-design.mjs +97 -0
  1226. package/template/.cursor/skills/yss-prototype-stage/tests/antd-reference.test.mjs +4 -24
  1227. package/template/.cursor/skills/yss-prototype-stage/tests/browser-harness.mjs +37 -0
  1228. package/template/.cursor/skills/yss-prototype-stage/tests/browser-visual.mjs +22 -0
  1229. package/template/.cursor/skills/yss-prototype-stage/tests/business-controls-browser.mjs +43 -0
  1230. package/template/.cursor/skills/yss-prototype-stage/tests/business-controls.test.mjs +20 -0
  1231. package/template/.cursor/skills/yss-prototype-stage/tests/compact-theme-browser.mjs +53 -0
  1232. package/template/.cursor/skills/yss-prototype-stage/tests/comparison-browser-smoke.mjs +77 -0
  1233. package/template/.cursor/skills/yss-prototype-stage/tests/comparison-fixture.mjs +16 -0
  1234. package/template/.cursor/skills/yss-prototype-stage/tests/comparison.test.mjs +46 -0
  1235. package/template/.cursor/skills/yss-prototype-stage/tests/components-browser.mjs +60 -0
  1236. package/template/.cursor/skills/yss-prototype-stage/tests/patterns-browser.mjs +84 -0
  1237. package/template/.cursor/skills/yss-prototype-stage/tests/reliability.test.mjs +34 -0
  1238. package/template/.cursor/skills/yss-prototype-stage/tests/retirement.test.mjs +8 -0
  1239. package/template/.cursor/skills/yss-prototype-stage/tests/run-scenarios.mjs +19 -2
  1240. package/template/.cursor/skills/yss-prototype-stage/tests/shadcn-vue.test.mjs +43 -0
  1241. package/template/.cursor/skills/yss-prototype-stage/tests/verification-entry.test.mjs +16 -0
  1242. package/template/.cursor/skills/yss-prototype-stage/tests/workbench-smoke.mjs +36 -21
  1243. package/template/.cursor/skills/yss-prototype-stage/tests/workspace-browser.mjs +50 -0
  1244. package/template/.cursor/skills/yss-prototype-stage/tests/workspace.test.mjs +70 -0
  1245. package/template/.cursor/skills/yss-prototype-stage/tests/zoom-browser.mjs +26 -0
  1246. package/template/.cursor/skills/yss-research/SKILL.md +4 -0
  1247. package/template/.cursor/skills/yss-stage-decision/SKILL.md +2 -0
  1248. package/template/.cursor/skills/yss-technical-design/SKILL.md +4 -0
  1249. package/template/.cursor/skills/yss-ui-business-page-generation/SKILL.md +4 -61
  1250. package/template/.cursor/skills/yss-ui-business-page-generation/references/page-composition-example.md +50 -0
  1251. package/template/.cursor/skills/yss-ui-business-page-generation/references/page-layout-example.md +19 -0
  1252. package/template/.cursor/skills/ytable-usage/SKILL.md +3 -191
  1253. package/template/.cursor/skills/ytable-usage/references/selection-and-batch.md +30 -0
  1254. package/template/.cursor/skills/ytable-usage/references/table-pagination-examples.md +170 -0
  1255. package/template/.pi/skills/archify/SKILL.md +4 -52
  1256. package/template/.pi/skills/archify/references/authoring-notes.md +12 -0
  1257. package/template/.pi/skills/archify/references/authoring-workflow.md +25 -0
  1258. package/template/.pi/skills/archify/references/delivery-workflow.md +25 -0
  1259. package/template/.pi/skills/archify/references/upstream-updates.md +12 -0
  1260. package/template/.pi/skills/code-review/SKILL.md +3 -34
  1261. package/template/.pi/skills/code-review/references/legacy-convergence.md +5 -0
  1262. package/template/.pi/skills/code-review/references/review-axis-checklists.md +18 -0
  1263. package/template/.pi/skills/code-review/references/smell-baseline.md +23 -0
  1264. package/template/.pi/skills/codebase-design/SKILL.md +4 -0
  1265. package/template/.pi/skills/codebase-design/references/architecture-audit.md +69 -0
  1266. package/template/.pi/skills/diagnosing-bugs/SKILL.md +3 -91
  1267. package/template/.pi/skills/diagnosing-bugs/references/feedback-loop.md +53 -0
  1268. package/template/.pi/skills/diagnosing-bugs/references/investigation.md +49 -0
  1269. package/template/.pi/skills/frontend-commit/SKILL.md +4 -93
  1270. package/template/.pi/skills/git-commit-core/SKILL.md +18 -0
  1271. package/template/.pi/skills/git-commit-core/agents/openai.yaml +2 -0
  1272. package/template/.pi/skills/java-backend-commit/SKILL.md +4 -96
  1273. package/template/.pi/skills/llm-wiki/SKILL.md +12 -13
  1274. package/template/.pi/skills/llm-wiki/assets/CLAUDE.md.template +7 -1
  1275. package/template/.pi/skills/llm-wiki/references/compile.md +21 -114
  1276. package/template/.pi/skills/llm-wiki/references/ingest.md +8 -33
  1277. package/template/.pi/skills/llm-wiki/references/lint.md +9 -46
  1278. package/template/.pi/skills/llm-wiki/references/query.md +9 -18
  1279. package/template/.pi/skills/llm-wiki/references/schema.md +56 -29
  1280. package/template/.pi/skills/llm-wiki/references/transactions.md +48 -0
  1281. package/template/.pi/skills/llm-wiki/references/writing.md +4 -4
  1282. package/template/.pi/skills/llm-wiki/scripts/advise.mjs +46 -58
  1283. package/template/.pi/skills/llm-wiki/scripts/advise.test.mjs +11 -16
  1284. package/template/.pi/skills/llm-wiki/scripts/core.mjs +262 -0
  1285. package/template/.pi/skills/llm-wiki/scripts/extract.mjs +35 -18
  1286. package/template/.pi/skills/llm-wiki/scripts/extract.test.mjs +5 -8
  1287. package/template/.pi/skills/llm-wiki/scripts/feedback.mjs +51 -0
  1288. package/template/.pi/skills/llm-wiki/scripts/inventory.mjs +43 -171
  1289. package/template/.pi/skills/llm-wiki/scripts/inventory.test.mjs +25 -18
  1290. package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.mjs +69 -92
  1291. package/template/.pi/skills/llm-wiki/scripts/lint-wikilinks.test.mjs +25 -37
  1292. package/template/.pi/skills/llm-wiki/scripts/migrate.mjs +51 -0
  1293. package/template/.pi/skills/llm-wiki/scripts/query.mjs +149 -0
  1294. package/template/.pi/skills/llm-wiki/scripts/regressions.test.mjs +101 -0
  1295. package/template/.pi/skills/llm-wiki/scripts/sources.mjs +166 -0
  1296. package/template/.pi/skills/llm-wiki/scripts/transaction.mjs +384 -0
  1297. package/template/.pi/skills/llm-wiki/scripts/v2.test.mjs +354 -0
  1298. package/template/.pi/skills/maintaining-skills/references/authoring.md +6 -0
  1299. package/template/.pi/skills/prototype/LOGIC.md +1 -1
  1300. package/template/.pi/skills/prototype/SKILL.md +5 -19
  1301. package/template/.pi/skills/prototype-review/SKILL.md +11 -0
  1302. package/template/.pi/skills/prototype-review/references/component-qa.md +32 -0
  1303. package/template/.pi/skills/setup-matt-pocock-skills/SKILL.md +4 -74
  1304. package/template/.pi/skills/setup-matt-pocock-skills/references/configuration-decisions.md +42 -0
  1305. package/template/.pi/skills/setup-matt-pocock-skills/references/write-configuration.md +42 -0
  1306. package/template/.pi/skills/to-spec/SKILL.md +9 -62
  1307. package/template/.pi/skills/to-tickets/SKILL.md +20 -86
  1308. package/template/.pi/skills/using-git-worktrees/SKILL.md +5 -122
  1309. package/template/.pi/skills/using-git-worktrees/references/git-fallback.md +46 -0
  1310. package/template/.pi/skills/using-git-worktrees/references/setup-and-baseline.md +45 -0
  1311. package/template/.pi/skills/using-git-worktrees/references/troubleshooting.md +47 -0
  1312. package/template/.pi/skills/wayfinder/SKILL.md +7 -86
  1313. package/template/.pi/skills/wayfinder/references/chart-map.md +14 -0
  1314. package/template/.pi/skills/wayfinder/references/map-format.md +49 -0
  1315. package/template/.pi/skills/wayfinder/references/scope-and-frontier.md +24 -0
  1316. package/template/.pi/skills/wayfinder/references/ticket-types.md +12 -0
  1317. package/template/.pi/skills/wayfinder/references/work-map.md +15 -0
  1318. package/template/.pi/skills/writing-for-agents/SKILL-MECHANICS.md +20 -11
  1319. package/template/.pi/skills/yedit-table-usage/SKILL.md +5 -172
  1320. package/template/.pi/skills/yedit-table-usage/references/editable-table-example.md +141 -0
  1321. package/template/.pi/skills/yedit-table-usage/references/select-and-filter-examples.md +38 -0
  1322. package/template/.pi/skills/yss-ddd-scaffold-generator/SKILL.md +4 -25
  1323. package/template/.pi/skills/yss-ddd-scaffold-generator/references/engineering-checks.md +11 -0
  1324. package/template/.pi/skills/yss-ddd-scaffold-generator/references/generation-workflow.md +14 -0
  1325. package/template/.pi/skills/yss-ddd-scaffold-generator/references/platform-selection.md +16 -0
  1326. package/template/.pi/skills/yss-design-system/SKILL.md +13 -3
  1327. package/template/.pi/skills/yss-design-system/assets/enterprise-craft/app.js +53 -0
  1328. package/template/.pi/skills/yss-design-system/assets/enterprise-craft/index.html +2 -0
  1329. package/template/.pi/skills/yss-design-system/assets/enterprise-craft/scenarios.js +14 -0
  1330. package/template/.pi/skills/yss-design-system/assets/enterprise-craft/styles.css +32 -0
  1331. package/template/.pi/skills/yss-design-system/references/data-quality-theme.md +2 -2
  1332. package/template/.pi/skills/yss-design-system/references/design-qa-theme.md +1 -1
  1333. package/template/.pi/skills/yss-design-system/references/design-system.md +3 -3
  1334. package/template/.pi/skills/yss-design-system/references/enterprise-craft.md +33 -0
  1335. package/template/.pi/skills/yss-design-system/references/page-composition.md +24 -0
  1336. package/template/.pi/skills/yss-design-system/references/prototype-default-theme.md +26 -0
  1337. package/template/.pi/skills/yss-design-system/references/search-date-theme.md +19 -0
  1338. package/template/.pi/skills/yss-design-system/scripts/export-craft-examples.mjs +30 -0
  1339. package/template/.pi/skills/yss-hook/SKILL.md +8 -102
  1340. package/template/.pi/skills/yss-hook/references/async-actions.md +49 -0
  1341. package/template/.pi/skills/yss-hook/references/list-pagination.md +46 -0
  1342. package/template/.pi/skills/yss-hook/references/polling.md +20 -0
  1343. package/template/.pi/skills/yss-implementation-contract-compiler/SKILL.md +8 -3
  1344. package/template/.pi/skills/yss-implementation-contract-compiler/references/boundaries.md +2 -3
  1345. package/template/.pi/skills/yss-implementation-contract-compiler/references/scaffold-compilation.md +7 -0
  1346. package/template/.pi/skills/yss-implementation-contract-compiler/references/yss-skill-execution-result.md +14 -0
  1347. package/template/.pi/skills/yss-openapi-draft-review/SKILL.md +2 -49
  1348. package/template/.pi/skills/yss-openapi-draft-review/references/review-output.md +45 -0
  1349. package/template/.pi/skills/yss-openapi-draft-review/references/semantic-review.md +16 -0
  1350. package/template/.pi/skills/yss-openapi-governance/SKILL.md +2 -48
  1351. package/template/.pi/skills/yss-openapi-governance/references/governance-workflow.md +38 -0
  1352. package/template/.pi/skills/yss-openapi-governance/references/locked-toolchain.md +22 -0
  1353. package/template/.pi/skills/yss-product-lifecycle/SKILL.md +24 -20
  1354. package/template/.pi/skills/yss-product-lifecycle/references/external-input-questionnaire.md +19 -0
  1355. package/template/.pi/skills/yss-product-lifecycle/references/matt-yss-adapter.md +5 -5
  1356. package/template/.pi/skills/yss-product-lifecycle/references/orchestration-contract.yaml +429 -384
  1357. package/template/.pi/skills/yss-product-lifecycle/references/orchestration.md +2 -2
  1358. package/template/.pi/skills/yss-product-lifecycle/references/plan-requirements.md +12 -0
  1359. package/template/.pi/skills/yss-product-lifecycle/references/state-model.md +3 -3
  1360. package/template/.pi/skills/yss-prototype-stage/SKILL.md +27 -8
  1361. package/template/.pi/skills/yss-prototype-stage/assets/comparison/comparison.css +12 -0
  1362. package/template/.pi/skills/yss-prototype-stage/assets/comparison/comparison.js +52 -0
  1363. package/template/.pi/skills/yss-prototype-stage/assets/comparison/index.html +6 -0
  1364. package/template/.pi/skills/yss-prototype-stage/assets/comparison/review-ready.js +2 -0
  1365. package/template/.pi/skills/yss-prototype-stage/assets/low-fidelity-exercise/app.js +17 -0
  1366. package/template/.pi/skills/yss-prototype-stage/assets/low-fidelity-exercise/index.html +1 -0
  1367. package/template/.pi/skills/yss-prototype-stage/assets/low-fidelity-exercise/styles.css +1 -0
  1368. package/template/.pi/skills/yss-prototype-stage/assets/native-workbench/app.js +12 -6
  1369. package/template/.pi/skills/yss-prototype-stage/assets/native-workbench/index.html +1 -1
  1370. package/template/.pi/skills/yss-prototype-stage/assets/native-workbench/scenarios.json +297 -0
  1371. package/template/.pi/skills/yss-prototype-stage/assets/native-workbench/styles.css +2 -0
  1372. package/template/.pi/skills/yss-prototype-stage/assets/offline-html/app.js +7 -5
  1373. package/template/.pi/skills/yss-prototype-stage/assets/offline-html/scenarios.json +297 -0
  1374. package/template/.pi/skills/yss-prototype-stage/assets/prototype-theme.css +92 -0
  1375. package/template/.pi/skills/yss-prototype-stage/assets/scenario-runtime.js +22 -0
  1376. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/SHADCN-LICENSE.txt +21 -0
  1377. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/package.json +23 -0
  1378. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/pnpm-lock.yaml +1278 -0
  1379. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/registry-manifest.json +936 -0
  1380. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/theme.css +107 -0
  1381. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/Alert.vue +21 -0
  1382. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/AlertDescription.vue +17 -0
  1383. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/AlertTitle.vue +17 -0
  1384. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert/index.ts +24 -0
  1385. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialog.vue +15 -0
  1386. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogAction.vue +18 -0
  1387. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogCancel.vue +25 -0
  1388. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogContent.vue +44 -0
  1389. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogDescription.vue +23 -0
  1390. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogFooter.vue +22 -0
  1391. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogHeader.vue +17 -0
  1392. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogTitle.vue +21 -0
  1393. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/AlertDialogTrigger.vue +12 -0
  1394. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/alert-dialog/index.ts +9 -0
  1395. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/badge/Badge.vue +26 -0
  1396. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/badge/index.ts +26 -0
  1397. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/Breadcrumb.vue +17 -0
  1398. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbEllipsis.vue +23 -0
  1399. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbItem.vue +17 -0
  1400. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbLink.vue +21 -0
  1401. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbList.vue +17 -0
  1402. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbPage.vue +20 -0
  1403. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/BreadcrumbSeparator.vue +22 -0
  1404. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/breadcrumb/index.ts +7 -0
  1405. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/button/Button.vue +31 -0
  1406. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/button/index.ts +40 -0
  1407. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/Card.vue +22 -0
  1408. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardAction.vue +17 -0
  1409. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardContent.vue +17 -0
  1410. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardDescription.vue +17 -0
  1411. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardFooter.vue +17 -0
  1412. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardHeader.vue +17 -0
  1413. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/CardTitle.vue +17 -0
  1414. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/card/index.ts +7 -0
  1415. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/checkbox/Checkbox.vue +35 -0
  1416. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/checkbox/index.ts +1 -0
  1417. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/Combobox.vue +19 -0
  1418. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxAnchor.vue +23 -0
  1419. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxEmpty.vue +21 -0
  1420. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxGroup.vue +27 -0
  1421. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxInput.vue +42 -0
  1422. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxItem.vue +24 -0
  1423. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxItemIndicator.vue +23 -0
  1424. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxList.vue +33 -0
  1425. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxSeparator.vue +21 -0
  1426. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxTrigger.vue +24 -0
  1427. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/ComboboxViewport.vue +23 -0
  1428. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/combobox/index.ts +13 -0
  1429. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/Dialog.vue +19 -0
  1430. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogClose.vue +15 -0
  1431. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogContent.vue +53 -0
  1432. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogDescription.vue +23 -0
  1433. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogFooter.vue +27 -0
  1434. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogHeader.vue +17 -0
  1435. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogOverlay.vue +21 -0
  1436. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogScrollContent.vue +59 -0
  1437. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogTitle.vue +23 -0
  1438. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/DialogTrigger.vue +15 -0
  1439. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dialog/index.ts +10 -0
  1440. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenu.vue +19 -0
  1441. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +39 -0
  1442. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuContent.vue +39 -0
  1443. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuGroup.vue +15 -0
  1444. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuItem.vue +31 -0
  1445. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuLabel.vue +23 -0
  1446. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuRadioGroup.vue +21 -0
  1447. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  1448. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSeparator.vue +23 -0
  1449. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuShortcut.vue +17 -0
  1450. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSub.vue +18 -0
  1451. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSubContent.vue +27 -0
  1452. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  1453. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/DropdownMenuTrigger.vue +17 -0
  1454. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/dropdown-menu/index.ts +16 -0
  1455. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/Empty.vue +20 -0
  1456. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyContent.vue +20 -0
  1457. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyDescription.vue +20 -0
  1458. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyHeader.vue +20 -0
  1459. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyMedia.vue +21 -0
  1460. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/EmptyTitle.vue +17 -0
  1461. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/empty/index.ts +26 -0
  1462. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/Field.vue +25 -0
  1463. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldContent.vue +20 -0
  1464. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldDescription.vue +22 -0
  1465. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldError.vue +53 -0
  1466. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldGroup.vue +20 -0
  1467. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldLabel.vue +23 -0
  1468. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldLegend.vue +24 -0
  1469. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldSeparator.vue +29 -0
  1470. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldSet.vue +21 -0
  1471. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/FieldTitle.vue +20 -0
  1472. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/field/index.ts +39 -0
  1473. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input/Input.vue +33 -0
  1474. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input/index.ts +1 -0
  1475. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroup.vue +35 -0
  1476. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupAddon.vue +36 -0
  1477. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupButton.vue +29 -0
  1478. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupInput.vue +19 -0
  1479. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupText.vue +19 -0
  1480. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/InputGroupTextarea.vue +19 -0
  1481. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/input-group/index.ts +51 -0
  1482. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/label/Label.vue +26 -0
  1483. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/label/index.ts +1 -0
  1484. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/Pagination.vue +26 -0
  1485. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationContent.vue +22 -0
  1486. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationEllipsis.vue +25 -0
  1487. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationFirst.vue +33 -0
  1488. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationItem.vue +34 -0
  1489. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationLast.vue +33 -0
  1490. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationNext.vue +33 -0
  1491. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/PaginationPrevious.vue +33 -0
  1492. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/pagination/index.ts +8 -0
  1493. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/Popover.vue +19 -0
  1494. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverAnchor.vue +15 -0
  1495. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverContent.vue +45 -0
  1496. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/PopoverTrigger.vue +15 -0
  1497. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/popover/index.ts +4 -0
  1498. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendar.vue +62 -0
  1499. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarCell.vue +23 -0
  1500. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarCellTrigger.vue +41 -0
  1501. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGrid.vue +23 -0
  1502. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridBody.vue +15 -0
  1503. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridHead.vue +15 -0
  1504. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarGridRow.vue +22 -0
  1505. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeadCell.vue +23 -0
  1506. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeader.vue +23 -0
  1507. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarHeading.vue +30 -0
  1508. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarNextButton.vue +32 -0
  1509. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/RangeCalendarPrevButton.vue +32 -0
  1510. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/range-calendar/index.ts +12 -0
  1511. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/Select.vue +19 -0
  1512. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectContent.vue +51 -0
  1513. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectGroup.vue +15 -0
  1514. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectItem.vue +44 -0
  1515. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectItemText.vue +15 -0
  1516. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectLabel.vue +17 -0
  1517. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectScrollDownButton.vue +26 -0
  1518. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectScrollUpButton.vue +26 -0
  1519. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectSeparator.vue +19 -0
  1520. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectTrigger.vue +33 -0
  1521. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/SelectValue.vue +15 -0
  1522. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/select/index.ts +11 -0
  1523. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/separator/Separator.vue +29 -0
  1524. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/separator/index.ts +1 -0
  1525. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/Sheet.vue +19 -0
  1526. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetClose.vue +15 -0
  1527. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetContent.vue +62 -0
  1528. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetDescription.vue +21 -0
  1529. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetFooter.vue +16 -0
  1530. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetHeader.vue +15 -0
  1531. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetOverlay.vue +21 -0
  1532. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetTitle.vue +21 -0
  1533. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/SheetTrigger.vue +15 -0
  1534. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/sheet/index.ts +8 -0
  1535. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/skeleton/Skeleton.vue +17 -0
  1536. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/skeleton/index.ts +1 -0
  1537. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/spinner/Spinner.vue +17 -0
  1538. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/spinner/index.ts +1 -0
  1539. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/Table.vue +16 -0
  1540. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableBody.vue +17 -0
  1541. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableCaption.vue +17 -0
  1542. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableCell.vue +22 -0
  1543. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableEmpty.vue +34 -0
  1544. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableFooter.vue +17 -0
  1545. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableHead.vue +17 -0
  1546. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableHeader.vue +17 -0
  1547. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/TableRow.vue +17 -0
  1548. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/table/index.ts +9 -0
  1549. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/Tabs.vue +24 -0
  1550. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsContent.vue +21 -0
  1551. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsList.vue +24 -0
  1552. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/TabsTrigger.vue +26 -0
  1553. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tabs/index.ts +4 -0
  1554. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/textarea/Textarea.vue +28 -0
  1555. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/textarea/index.ts +1 -0
  1556. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/Tooltip.vue +19 -0
  1557. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipContent.vue +34 -0
  1558. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipProvider.vue +14 -0
  1559. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/TooltipTrigger.vue +15 -0
  1560. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/ui/tooltip/index.ts +4 -0
  1561. package/template/.pi/skills/yss-prototype-stage/assets/shadcn-vue-authoring/utils.ts +7 -0
  1562. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/Analysis.vue +16 -0
  1563. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/Approval.vue +14 -0
  1564. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/CombinedQuery.vue +17 -0
  1565. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/ComponentStates.vue +41 -0
  1566. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/Conflict.vue +33 -0
  1567. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/DateRange.vue +29 -0
  1568. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/Frame.vue +7 -0
  1569. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/ListDetail.vue +47 -0
  1570. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/MultiStep.vue +24 -0
  1571. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/Notice.vue +5 -0
  1572. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/OwnerValidity.vue +26 -0
  1573. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/SearchSelect.vue +32 -0
  1574. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/Workspace.vue +174 -0
  1575. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/analysis-standard.config.json +6 -0
  1576. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/analysis-standard.ts +3 -0
  1577. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/analysis.scenarios.json +276 -0
  1578. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/approval-standard.config.json +6 -0
  1579. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/approval-standard.ts +3 -0
  1580. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/approval.scenarios.json +207 -0
  1581. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/business-controls.css +14 -0
  1582. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/business-controls.js +24 -0
  1583. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query-standard.config.json +6 -0
  1584. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query-standard.ts +3 -0
  1585. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/combined-query.scenarios.json +298 -0
  1586. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/component-states-standard.config.json +6 -0
  1587. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/component-states-standard.ts +3 -0
  1588. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/conflict-standard.config.json +6 -0
  1589. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/conflict-standard.ts +3 -0
  1590. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/conflict.scenarios.json +229 -0
  1591. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-glass.config.json +6 -0
  1592. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-glass.ts +3 -0
  1593. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-standard.config.json +6 -0
  1594. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail-standard.ts +3 -0
  1595. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/list-detail.scenarios.json +185 -0
  1596. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/mount.ts +4 -0
  1597. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-glass.config.json +6 -0
  1598. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-glass.ts +3 -0
  1599. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-standard.config.json +6 -0
  1600. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step-standard.ts +3 -0
  1601. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/multi-step.scenarios.json +188 -0
  1602. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity-standard.config.json +6 -0
  1603. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity-standard.ts +3 -0
  1604. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/owner-validity.scenarios.json +298 -0
  1605. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/patterns.css +26 -0
  1606. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/refinement.css +129 -0
  1607. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workbench.ts +1 -0
  1608. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-definition.ts +40 -0
  1609. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-glass.config.json +6 -0
  1610. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-glass.ts +3 -0
  1611. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-model.js +75 -0
  1612. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-page.ts +18 -0
  1613. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-standard.config.json +6 -0
  1614. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace-standard.ts +3 -0
  1615. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.css +101 -0
  1616. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.scenarios.json +2015 -0
  1617. package/template/.pi/skills/yss-prototype-stage/assets/vue-business-patterns/workspace.ts +26 -0
  1618. package/template/.pi/skills/yss-prototype-stage/references/business-patterns.md +42 -0
  1619. package/template/.pi/skills/yss-prototype-stage/references/comparison-tool.md +48 -0
  1620. package/template/.pi/skills/yss-prototype-stage/references/component-recipes.md +41 -0
  1621. package/template/.pi/skills/yss-prototype-stage/references/concept-comparison.md +26 -0
  1622. package/template/.pi/skills/yss-prototype-stage/references/enterprise-workspace.md +53 -0
  1623. package/template/.pi/skills/yss-prototype-stage/references/low-fidelity-exercise.md +32 -0
  1624. package/template/.pi/skills/yss-prototype-stage/references/product-design-adapter.md +11 -5
  1625. package/template/.pi/skills/yss-prototype-stage/references/prototype-profile-routing.md +10 -6
  1626. package/template/.pi/skills/yss-prototype-stage/references/prototype-verification.md +25 -0
  1627. package/template/.pi/skills/yss-prototype-stage/references/resource-lifecycle.md +20 -0
  1628. package/template/.pi/skills/yss-prototype-stage/references/search-date-patterns.md +28 -0
  1629. package/template/.pi/skills/yss-prototype-stage/references/shadcn-integration.md +5 -0
  1630. package/template/.pi/skills/yss-prototype-stage/references/shadcn-vue-integration.md +46 -0
  1631. package/template/.pi/skills/yss-prototype-stage/references/usability-research.md +26 -0
  1632. package/template/.pi/skills/yss-prototype-stage/scripts/browser-session.mjs +57 -0
  1633. package/template/.pi/skills/yss-prototype-stage/scripts/build-shadcn-vue-prototype.mjs +137 -0
  1634. package/template/.pi/skills/yss-prototype-stage/scripts/compose-workspace-scenarios.mjs +22 -0
  1635. package/template/.pi/skills/yss-prototype-stage/scripts/export-business-patterns.mjs +7 -0
  1636. package/template/.pi/skills/yss-prototype-stage/scripts/export-low-fidelity-exercise.mjs +18 -0
  1637. package/template/.pi/skills/yss-prototype-stage/scripts/export-vue-patterns.mjs +21 -0
  1638. package/template/.pi/skills/yss-prototype-stage/scripts/offline-html.mjs +60 -23
  1639. package/template/.pi/skills/yss-prototype-stage/scripts/prototype-comparison.mjs +208 -0
  1640. package/template/.pi/skills/yss-prototype-stage/scripts/prototype-contract.mjs +19 -14
  1641. package/template/.pi/skills/yss-prototype-stage/scripts/scenario-contract.mjs +31 -0
  1642. package/template/.pi/skills/yss-prototype-stage/scripts/verify-prototype-design.mjs +97 -0
  1643. package/template/.pi/skills/yss-prototype-stage/tests/antd-reference.test.mjs +4 -24
  1644. package/template/.pi/skills/yss-prototype-stage/tests/browser-harness.mjs +37 -0
  1645. package/template/.pi/skills/yss-prototype-stage/tests/browser-visual.mjs +22 -0
  1646. package/template/.pi/skills/yss-prototype-stage/tests/business-controls-browser.mjs +43 -0
  1647. package/template/.pi/skills/yss-prototype-stage/tests/business-controls.test.mjs +20 -0
  1648. package/template/.pi/skills/yss-prototype-stage/tests/compact-theme-browser.mjs +53 -0
  1649. package/template/.pi/skills/yss-prototype-stage/tests/comparison-browser-smoke.mjs +77 -0
  1650. package/template/.pi/skills/yss-prototype-stage/tests/comparison-fixture.mjs +16 -0
  1651. package/template/.pi/skills/yss-prototype-stage/tests/comparison.test.mjs +46 -0
  1652. package/template/.pi/skills/yss-prototype-stage/tests/components-browser.mjs +60 -0
  1653. package/template/.pi/skills/yss-prototype-stage/tests/patterns-browser.mjs +84 -0
  1654. package/template/.pi/skills/yss-prototype-stage/tests/reliability.test.mjs +34 -0
  1655. package/template/.pi/skills/yss-prototype-stage/tests/retirement.test.mjs +8 -0
  1656. package/template/.pi/skills/yss-prototype-stage/tests/run-scenarios.mjs +19 -2
  1657. package/template/.pi/skills/yss-prototype-stage/tests/shadcn-vue.test.mjs +43 -0
  1658. package/template/.pi/skills/yss-prototype-stage/tests/verification-entry.test.mjs +16 -0
  1659. package/template/.pi/skills/yss-prototype-stage/tests/workbench-smoke.mjs +36 -21
  1660. package/template/.pi/skills/yss-prototype-stage/tests/workspace-browser.mjs +50 -0
  1661. package/template/.pi/skills/yss-prototype-stage/tests/workspace.test.mjs +70 -0
  1662. package/template/.pi/skills/yss-prototype-stage/tests/zoom-browser.mjs +26 -0
  1663. package/template/.pi/skills/yss-research/SKILL.md +4 -0
  1664. package/template/.pi/skills/yss-stage-decision/SKILL.md +2 -0
  1665. package/template/.pi/skills/yss-technical-design/SKILL.md +4 -0
  1666. package/template/.pi/skills/yss-ui-business-page-generation/SKILL.md +4 -61
  1667. package/template/.pi/skills/yss-ui-business-page-generation/references/page-composition-example.md +50 -0
  1668. package/template/.pi/skills/yss-ui-business-page-generation/references/page-layout-example.md +19 -0
  1669. package/template/.pi/skills/ytable-usage/SKILL.md +3 -191
  1670. package/template/.pi/skills/ytable-usage/references/selection-and-batch.md +30 -0
  1671. package/template/.pi/skills/ytable-usage/references/table-pagination-examples.md +170 -0
  1672. package/template/.template-spec/agents/README.md +1 -1
  1673. package/template/.template-spec/agents/digital-human-roles.yaml +3 -3
  1674. package/template/.template-spec/agents/issue-tracker.md +10 -1
  1675. package/template/.template-spec/agents/skill-migrations.md +15 -0
  1676. package/template/.template-spec/agents/yss-skill-registry.yaml +51 -29
  1677. package/template/.template-spec/architecture/README.md +3 -34
  1678. package/template/.template-spec/design/README.md +7 -2
  1679. package/template/.template-spec/design/design.md +30 -35
  1680. package/template/.template-spec/design/templates/examples/model-publishing-interaction.example.md +2 -2
  1681. package/template/.template-spec/design/templates/interaction-spec-template.md +24 -0
  1682. package/template/.template-spec/design/templates/prototype-evidence-template.yaml +18 -5
  1683. package/template/.template-spec/design/templates/prototype-review-checklist.md +8 -0
  1684. package/template/.template-spec/design/tokens/.design-md-projection.json +2 -2
  1685. package/template/.template-spec/design/tokens/variables.css +162 -0
  1686. package/template/.template-spec/plan/templates/competitive-analysis-template.md +2 -2
  1687. package/template/.template-spec/plan/templates/plan-template.md +25 -1
  1688. package/template/.template-spec/process/business-tickets.md +48 -0
  1689. package/template/.template-spec/process/checkpoint-boundary.yaml +73 -0
  1690. package/template/.template-spec/process/contract-reading.md +59 -0
  1691. package/template/.template-spec/process/document-writing.md +2 -0
  1692. package/template/.template-spec/process/feature-assets.md +38 -0
  1693. package/template/.template-spec/process/lifecycle-artifact-map.md +1 -0
  1694. package/template/.template-spec/process/lifecycle-registry-baseline.json +10 -4
  1695. package/template/.template-spec/process/lifecycle-registry.yaml +21 -5
  1696. package/template/.template-spec/process/plan-spec-quality.md +69 -0
  1697. package/template/.template-spec/process/project-ci.md +21 -0
  1698. package/template/.template-spec/process/reading-policy.yaml +4 -0
  1699. package/template/.template-spec/process/research-completion.md +23 -0
  1700. package/template/.template-spec/process/schemas/business-tickets-v1.schema.json +449 -0
  1701. package/template/.template-spec/process/schemas/digital-human-task-package.schema.json +202 -12
  1702. package/template/.template-spec/process/schemas/domain-strategy-reading.schema.json +216 -0
  1703. package/template/.template-spec/process/schemas/frontend-implementation-evidence.schema.json +7 -15
  1704. package/template/.template-spec/process/schemas/lifecycle-checkpoint.schema.json +203 -11
  1705. package/template/.template-spec/process/schemas/reading-manifest.schema.json +14 -0
  1706. package/template/.template-spec/process/schemas/reading-policy.schema.json +10 -0
  1707. package/template/.template-spec/process/schemas/stage-decision-package-reading.schema.json +148 -0
  1708. package/template/.template-spec/process/stage-tracking.md +8 -0
  1709. package/template/.template-spec/process/strategic-handoff-package.md +3 -1
  1710. package/template/.template-spec/process/subagent-collaboration.md +8 -0
  1711. package/template/.template-spec/process/templates/frontend-implementation-verification-template.yaml +15 -1
  1712. package/template/.template-spec/process/templates/stage-checkpoint-template.md +6 -1
  1713. package/template/.template-spec/templates/business-ticket-review-template.yaml +11 -0
  1714. package/template/.template-spec/templates/business-ticket-set-template.yaml +16 -0
  1715. package/template/.template-spec/templates/business-ticket-template.md +38 -0
  1716. package/template/.template-spec/templates/examples/lifecycle-writing-examples.md +16 -0
  1717. package/template/.template-spec/templates/examples/plan-spec/complex-defective.md +38 -0
  1718. package/template/.template-spec/templates/examples/plan-spec/complex-source.md +12 -0
  1719. package/template/.template-spec/templates/examples/plan-spec/complex-valid.md +38 -0
  1720. package/template/.template-spec/templates/examples/plan-spec/expectations.json +46 -0
  1721. package/template/.template-spec/templates/examples/plan-spec/high-risk-before.md +32 -0
  1722. package/template/.template-spec/templates/examples/plan-spec/high-risk-defective.md +39 -0
  1723. package/template/.template-spec/templates/examples/plan-spec/high-risk-source.md +11 -0
  1724. package/template/.template-spec/templates/examples/plan-spec/high-risk-valid.md +39 -0
  1725. package/template/.template-spec/templates/examples/plan-spec/ordinary-defective.md +36 -0
  1726. package/template/.template-spec/templates/examples/plan-spec/ordinary-plan.md +27 -0
  1727. package/template/.template-spec/templates/examples/plan-spec/ordinary-source.md +14 -0
  1728. package/template/.template-spec/templates/examples/plan-spec/ordinary-valid.md +36 -0
  1729. package/template/.template-spec/templates/local-parent-ticket-template.md +23 -15
  1730. package/template/.template-spec/templates/spec-delta-template.md +7 -5
  1731. package/template/.template-spec/templates/spec-template.md +31 -15
  1732. package/template/.template-spec/templates/vertical-slice-ticket-template.md +4 -0
  1733. package/template/AGENTS.md +2 -2
  1734. package/template/CONTEXT.md +6 -1
  1735. package/template/DESIGN.md +23 -4
  1736. package/template/README.md +12 -24
  1737. package/template/scripts/contract +17 -5
  1738. package/template/scripts/feature-assets +23 -0
  1739. package/template/scripts/inspect-plan-spec +32 -0
  1740. package/template/scripts/inspect-skill-discovery +24 -0
  1741. package/template/scripts/lib/business-ticket-lifecycle.mjs +34 -0
  1742. package/template/scripts/lib/business-tickets.mjs +273 -0
  1743. package/template/scripts/lib/checkpoint-boundary.mjs +40 -0
  1744. package/template/scripts/lib/contract-views.mjs +77 -9
  1745. package/template/scripts/lib/execution-evidence.mjs +51 -0
  1746. package/template/scripts/lib/feature-assets.mjs +274 -0
  1747. package/template/scripts/lib/governance-io.mjs +40 -0
  1748. package/template/scripts/lib/harness-execution-scope.mjs +1 -1
  1749. package/template/scripts/lib/implementation-contract-compiler.mjs +2 -0
  1750. package/template/scripts/lib/lifecycle-context-query.mjs +15 -3
  1751. package/template/scripts/lib/lifecycle-status.mjs +49 -7
  1752. package/template/scripts/lib/lifecycle-transition.mjs +31 -4
  1753. package/template/scripts/lib/maintenance-research.mjs +63 -0
  1754. package/template/scripts/lib/plan-spec-markdown.mjs +97 -0
  1755. package/template/scripts/lib/plan-spec-quality.mjs +289 -0
  1756. package/template/scripts/lib/project-ci-install.mjs +98 -0
  1757. package/template/scripts/lib/project-governance.mjs +189 -0
  1758. package/template/scripts/lib/read-only-intake.mjs +132 -0
  1759. package/template/scripts/lib/reading-view-adapters.mjs +62 -0
  1760. package/template/scripts/lib/reading-view-bundle.mjs +201 -0
  1761. package/template/scripts/lib/reading-view-diff.mjs +29 -0
  1762. package/template/scripts/lib/reading-view-markdown.mjs +39 -0
  1763. package/template/scripts/lib/reading-view-model.mjs +13 -0
  1764. package/template/scripts/lib/reading-view-policy.mjs +16 -0
  1765. package/template/scripts/lib/skill-discovery.mjs +150 -0
  1766. package/template/scripts/lib/skill-registry.mjs +43 -2
  1767. package/template/scripts/lib/skill-supply-chain.mjs +5 -1
  1768. package/template/scripts/lib/slice-contract-preparation.mjs +8 -2
  1769. package/template/scripts/lib/slice-contract.mjs +15 -1
  1770. package/template/scripts/lib/slice-task-package.mjs +1 -1
  1771. package/template/scripts/lib/stage-tracking-migration.mjs +9 -1
  1772. package/template/scripts/lib/stage-tracking.mjs +10 -5
  1773. package/template/scripts/lib/strategic-handoff-consumption.mjs +14 -2
  1774. package/template/scripts/lib/strategic-handoff-io.mjs +6 -2
  1775. package/template/scripts/lib/strategic-handoff.mjs +26 -5
  1776. package/template/scripts/lib/task-package.mjs +22 -4
  1777. package/template/scripts/lib/testing/user-decision-fixture.mjs +33 -0
  1778. package/template/scripts/lib/user-decision-reuse.mjs +1 -1
  1779. package/template/scripts/lifecycle-status +13 -3
  1780. package/template/scripts/prepare-read-only-intake +16 -0
  1781. package/template/scripts/project-ci +20 -0
  1782. package/template/scripts/project-ci-transition +13 -0
  1783. package/template/scripts/query-lifecycle-context +4 -0
  1784. package/template/scripts/run-read-only-intake +14 -0
  1785. package/template/scripts/stage-tracking +1 -0
  1786. package/template/scripts/vendor/NOTICES.md +237 -0
  1787. package/template/scripts/vendor/manifest.json +1216 -65
  1788. package/template/scripts/vendor/markdown.mjs +11783 -0
  1789. package/template/scripts/verify-approval-record +4 -1
  1790. package/template/scripts/verify-business-tickets +11 -0
  1791. package/template/scripts/verify-context-contract +4 -1
  1792. package/template/scripts/verify-digital-human-task-package +5 -2
  1793. package/template/scripts/verify-frontend-implementation-evidence +24 -1
  1794. package/template/scripts/verify-lifecycle-checkpoint +17 -2
  1795. package/template/scripts/verify-maintenance-research +13 -0
  1796. package/template/scripts/verify-prototype-design +3 -0
  1797. package/template/skills-lock.json +44 -101
  1798. package/template.manifest.json +119 -29
  1799. package/template.snapshot.json +5 -6
  1800. package/template/.agents/skills/grill-with-docs/SKILL.md +0 -20
  1801. package/template/.agents/skills/grill-with-docs/agents/openai.yaml +0 -5
  1802. package/template/.agents/skills/improve-codebase-architecture/SKILL.md +0 -75
  1803. package/template/.agents/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
  1804. package/template/.agents/skills/prototype/UI.md +0 -112
  1805. package/template/.agents/skills/setup-matt-pocock-skills/domain.md +0 -37
  1806. package/template/.agents/skills/to-questionnaire/SKILL.md +0 -55
  1807. package/template/.agents/skills/to-questionnaire/agents/openai.yaml +0 -5
  1808. package/template/.agents/skills/wait-what/SKILL.md +0 -7
  1809. package/template/.agents/skills/wait-what/agents/openai.yaml +0 -5
  1810. package/template/.agents/skills/yss-prototype-stage/assets/antd-authoring/package.json +0 -16
  1811. package/template/.agents/skills/yss-prototype-stage/assets/antd-authoring/pnpm-lock.yaml +0 -1678
  1812. package/template/.agents/skills/yss-prototype-stage/assets/antd-authoring/workbench.jsx +0 -23
  1813. package/template/.agents/skills/yss-prototype-stage/references/antd-component-catalog.json +0 -736
  1814. package/template/.agents/skills/yss-prototype-stage/references/antd-integration.md +0 -61
  1815. package/template/.agents/skills/yss-prototype-stage/scripts/build-antd-prototype.mjs +0 -71
  1816. package/template/.agents/skills/yss-prototype-stage/scripts/collect-antd-reference.mjs +0 -26
  1817. package/template/.codex/skills/data-analytics/.app.json +0 -84
  1818. package/template/.codex/skills/data-analytics/.codex-plugin/plugin.json +0 -66
  1819. package/template/.codex/skills/data-analytics/.mcp.json +0 -30
  1820. package/template/.codex/skills/data-analytics/AGENTS.md +0 -20
  1821. package/template/.codex/skills/data-analytics/DEPENDENCIES.MD +0 -27
  1822. package/template/.codex/skills/data-analytics/README.md +0 -60
  1823. package/template/.codex/skills/data-analytics/__yss_dotfile__.gitignore +0 -2
  1824. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html +0 -16
  1825. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part001 +0 -1
  1826. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part002 +0 -1
  1827. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part003 +0 -1
  1828. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part004 +0 -1
  1829. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part005 +0 -1
  1830. package/template/.codex/skills/data-analytics/assets/datascience-artifact-widget.html.gz.b64.part006 +0 -1
  1831. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html +0 -16
  1832. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part001 +0 -1
  1833. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part002 +0 -1
  1834. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part003 +0 -1
  1835. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part004 +0 -1
  1836. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part005 +0 -1
  1837. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part006 +0 -1
  1838. package/template/.codex/skills/data-analytics/assets/datascience-chart-widget.html.gz.b64.part007 +0 -1
  1839. package/template/.codex/skills/data-analytics/assets/datascience-small.svg +0 -5
  1840. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html +0 -16
  1841. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part001 +0 -1
  1842. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part002 +0 -1
  1843. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part003 +0 -1
  1844. package/template/.codex/skills/data-analytics/assets/datascience-table-widget.html.gz.b64.part004 +0 -1
  1845. package/template/.codex/skills/data-analytics/assets/datascience.png +0 -0
  1846. package/template/.codex/skills/data-analytics/assets/datascience.svg +0 -10
  1847. package/template/.codex/skills/data-analytics/mcp/server.cjs +0 -2964
  1848. package/template/.codex/skills/data-analytics/package-lock.json +0 -3048
  1849. package/template/.codex/skills/data-analytics/package.json +0 -43
  1850. package/template/.codex/skills/data-analytics/scripts/normalize-widget-assets.mjs +0 -75
  1851. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/SKILL.md +0 -137
  1852. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/agents/openai.yaml +0 -6
  1853. package/template/.codex/skills/data-analytics/skills/analyze-data-quality/references/quality-checks.md +0 -29
  1854. package/template/.codex/skills/data-analytics/skills/build-dashboard/SKILL.md +0 -148
  1855. package/template/.codex/skills/data-analytics/skills/build-dashboard/agents/openai.yaml +0 -6
  1856. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/bi-platform-dashboard.md +0 -18
  1857. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/html-dashboard.md +0 -24
  1858. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/mcp-artifact-dashboard.md +0 -71
  1859. package/template/.codex/skills/data-analytics/skills/build-dashboard/specifications/streamlit-dashboard.md +0 -85
  1860. package/template/.codex/skills/data-analytics/skills/build-report/SKILL.md +0 -207
  1861. package/template/.codex/skills/data-analytics/skills/build-report/agents/openai.yaml +0 -6
  1862. package/template/.codex/skills/data-analytics/skills/build-report/assets/executive-report-shell.html +0 -70
  1863. package/template/.codex/skills/data-analytics/skills/build-report/assets/technical-report-shell.html +0 -66
  1864. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/SKILL.md +0 -108
  1865. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/agents/openai.yaml +0 -6
  1866. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/__init__.py +0 -1
  1867. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/cli.py +0 -52
  1868. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/constants.py +0 -61
  1869. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/docx_writer.py +0 -362
  1870. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/html_parser.py +0 -829
  1871. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/model.py +0 -30
  1872. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/plan.py +0 -127
  1873. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/quality.py +0 -374
  1874. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/rendering.py +0 -613
  1875. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/table_utils.py +0 -54
  1876. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc/utils.py +0 -16
  1877. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/scripts/report_to_google_doc_plan.py +0 -9
  1878. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-doc/tests/test_delivery_plan.py +0 -45
  1879. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/SKILL.md +0 -77
  1880. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/agents/openai.yaml +0 -6
  1881. package/template/.codex/skills/data-analytics/skills/build-report/report-to-google-slides/scripts/report_to_google_slides.py +0 -2379
  1882. package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/SKILL.md +0 -88
  1883. package/template/.codex/skills/data-analytics/skills/build-report/report-to-pdf/agents/openai.yaml +0 -6
  1884. package/template/.codex/skills/data-analytics/skills/build-report/specifications/executive-report.md +0 -97
  1885. package/template/.codex/skills/data-analytics/skills/build-report/specifications/mcp-app-report.md +0 -59
  1886. package/template/.codex/skills/data-analytics/skills/build-report/specifications/technical-report.md +0 -75
  1887. package/template/.codex/skills/data-analytics/skills/design-kpis/SKILL.md +0 -103
  1888. package/template/.codex/skills/data-analytics/skills/design-kpis/agents/openai.yaml +0 -6
  1889. package/template/.codex/skills/data-analytics/skills/gather-business-context/SKILL.md +0 -68
  1890. package/template/.codex/skills/data-analytics/skills/gather-business-context/agents/openai.yaml +0 -6
  1891. package/template/.codex/skills/data-analytics/skills/index/SKILL.md +0 -251
  1892. package/template/.codex/skills/data-analytics/skills/index/agents/openai.yaml +0 -6
  1893. package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/SKILL.md +0 -131
  1894. package/template/.codex/skills/data-analytics/skills/jupyter-notebooks/agents/openai.yaml +0 -6
  1895. package/template/.codex/skills/data-analytics/skills/kpi-reporting/SKILL.md +0 -141
  1896. package/template/.codex/skills/data-analytics/skills/kpi-reporting/agents/openai.yaml +0 -6
  1897. package/template/.codex/skills/data-analytics/skills/kpi-reporting/references/report-templates.md +0 -32
  1898. package/template/.codex/skills/data-analytics/skills/market-sizing/SKILL.md +0 -106
  1899. package/template/.codex/skills/data-analytics/skills/market-sizing/agents/openai.yaml +0 -6
  1900. package/template/.codex/skills/data-analytics/skills/metric-diagnostics/SKILL.md +0 -130
  1901. package/template/.codex/skills/data-analytics/skills/metric-diagnostics/agents/openai.yaml +0 -6
  1902. package/template/.codex/skills/data-analytics/skills/product-business-analysis/SKILL.md +0 -141
  1903. package/template/.codex/skills/data-analytics/skills/product-business-analysis/agents/openai.yaml +0 -6
  1904. package/template/.codex/skills/data-analytics/skills/spreadsheets/SKILL.md +0 -178
  1905. package/template/.codex/skills/data-analytics/skills/spreadsheets/agents/openai.yaml +0 -9
  1906. package/template/.codex/skills/data-analytics/skills/spreadsheets/assets/file-spreadsheet.png +0 -0
  1907. package/template/.codex/skills/data-analytics/skills/spreadsheets/charts.md +0 -31
  1908. package/template/.codex/skills/data-analytics/skills/spreadsheets/references/artifact_tool_api.md +0 -466
  1909. package/template/.codex/skills/data-analytics/skills/spreadsheets/style_guidelines.md +0 -99
  1910. package/template/.codex/skills/data-analytics/skills/user-context/SKILL.md +0 -197
  1911. package/template/.codex/skills/data-analytics/skills/user-context/agents/openai.yaml +0 -6
  1912. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/automation-config.md +0 -26
  1913. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/source-category-config.json +0 -51
  1914. package/template/.codex/skills/data-analytics/skills/user-context/plugin-author-config/user-context-config.md +0 -66
  1915. package/template/.codex/skills/data-analytics/skills/user-context/references/automation.md +0 -69
  1916. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-examples.md +0 -204
  1917. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding-state-template.json +0 -87
  1918. package/template/.codex/skills/data-analytics/skills/user-context/references/onboarding.md +0 -497
  1919. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/connector-playbook.md +0 -74
  1920. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/setup.md +0 -65
  1921. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/skill-template.md +0 -160
  1922. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/source-intake.md +0 -75
  1923. package/template/.codex/skills/data-analytics/skills/user-context/references/semantic-layer/weekly-polling-automation.md +0 -96
  1924. package/template/.codex/skills/data-analytics/skills/user-context/references/source-category-runtime.md +0 -263
  1925. package/template/.codex/skills/data-analytics/skills/user-context/scripts/data_analytics_preflight.py +0 -1462
  1926. package/template/.codex/skills/data-analytics/skills/user-context/scripts/init_user_context_state.py +0 -128
  1927. package/template/.codex/skills/data-analytics/skills/user-context/scripts/reset_user_context_state.py +0 -101
  1928. package/template/.codex/skills/data-analytics/skills/user-context/scripts/validate_user_context_preflight.py +0 -499
  1929. package/template/.codex/skills/data-analytics/skills/user-context/tests/test_state_helpers.py +0 -978
  1930. package/template/.codex/skills/data-analytics/skills/validate-data/SKILL.md +0 -126
  1931. package/template/.codex/skills/data-analytics/skills/validate-data/agents/openai.yaml +0 -6
  1932. package/template/.codex/skills/data-analytics/skills/validate-data/references/validation-methods.md +0 -70
  1933. package/template/.codex/skills/data-analytics/skills/visualize-data/SKILL.md +0 -157
  1934. package/template/.codex/skills/data-analytics/skills/visualize-data/agents/openai.yaml +0 -6
  1935. package/template/.codex/skills/data-analytics/skills/visualize-data/references/seaborn-templates.md +0 -774
  1936. package/template/.codex/skills/data-analytics/src/DESIGN.md +0 -222
  1937. package/template/.codex/skills/data-analytics/src/analytics-app/App.tsx +0 -3666
  1938. package/template/.codex/skills/data-analytics/src/analytics-app/analytics-layout.test.mjs +0 -136
  1939. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartFrame.tsx +0 -54
  1940. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartLegend.tsx +0 -96
  1941. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartRenderer.tsx +0 -1647
  1942. package/template/.codex/skills/data-analytics/src/analytics-app/charting/ChartTooltip.tsx +0 -245
  1943. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-app-helpers.tsx +0 -462
  1944. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-capabilities.ts +0 -107
  1945. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-compatibility.ts +0 -164
  1946. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-contract.ts +0 -192
  1947. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-theme.ts +0 -203
  1948. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-tokens.css +0 -619
  1949. package/template/.codex/skills/data-analytics/src/analytics-app/charting/chart-transforms.ts +0 -402
  1950. package/template/.codex/skills/data-analytics/src/analytics-app/fonts/SystemSansVariableVF.woff2 +0 -0
  1951. package/template/.codex/skills/data-analytics/src/analytics-app/imageExport.ts +0 -370
  1952. package/template/.codex/skills/data-analytics/src/analytics-app/layout/AnalyticsLayoutCanvas.tsx +0 -536
  1953. package/template/.codex/skills/data-analytics/src/analytics-app/layout/RichMarkdown.tsx +0 -681
  1954. package/template/.codex/skills/data-analytics/src/analytics-app/layout/analyticsLayoutCore.ts +0 -164
  1955. package/template/.codex/skills/data-analytics/src/analytics-app/main.tsx +0 -21
  1956. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/chart_contract.py +0 -472
  1957. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/check_analytics_app_runtime_links.py +0 -75
  1958. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/design_contract.py +0 -142
  1959. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/package_utils.py +0 -142
  1960. package/template/.codex/skills/data-analytics/src/analytics-app/scripts/tests/test_package_utils.py +0 -377
  1961. package/template/.codex/skills/data-analytics/src/analytics-app/styles.css +0 -3468
  1962. package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.d.ts +0 -44
  1963. package/template/.codex/skills/data-analytics/src/analytics-app/tables/DataTable.jsx +0 -639
  1964. package/template/.codex/skills/data-analytics/src/analytics-app/tables/data-table.css +0 -327
  1965. package/template/.codex/skills/data-analytics/src/analytics-app/tokens.css +0 -225
  1966. package/template/.codex/skills/data-analytics/src/analytics-app/types.ts +0 -204
  1967. package/template/.codex/skills/data-analytics/src/analytics-app-core.md +0 -85
  1968. package/template/.codex/skills/data-analytics/src/codex-style-contract.md +0 -30
  1969. package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.html +0 -12
  1970. package/template/.codex/skills/data-analytics/src/datascience-artifact-widget.jsx +0 -1008
  1971. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.css +0 -2117
  1972. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.html +0 -122
  1973. package/template/.codex/skills/data-analytics/src/datascience-chart-widget.js +0 -3588
  1974. package/template/.codex/skills/data-analytics/src/datascience-table-widget.css +0 -483
  1975. package/template/.codex/skills/data-analytics/src/datascience-table-widget.html +0 -32
  1976. package/template/.codex/skills/data-analytics/src/datascience-table-widget.js +0 -333
  1977. package/template/.codex/skills/data-analytics/src/mcp-host.js +0 -153
  1978. package/template/.codex/skills/data-analytics/src/recharts-config.js +0 -315
  1979. package/template/.codex/skills/data-analytics/src/recharts-renderer.jsx +0 -294
  1980. package/template/.codex/skills/data-analytics/src/sql-source-view.css +0 -33
  1981. package/template/.codex/skills/data-analytics/src/sql-source-view.js +0 -157
  1982. package/template/.codex/skills/data-analytics/src/styles/codex-theme.css +0 -121
  1983. package/template/.codex/skills/data-analytics/src/table-renderer.jsx +0 -28
  1984. package/template/.codex/skills/data-analytics/tests/chart-transforms.test.mjs +0 -87
  1985. package/template/.codex/skills/data-analytics/tests/funnel-smoke.html +0 -105
  1986. package/template/.codex/skills/data-analytics/tests/inline-widget-compare.html +0 -233
  1987. package/template/.codex/skills/data-analytics/tests/mcp-server.test.mjs +0 -1500
  1988. package/template/.codex/skills/data-analytics/tests/native-style-contract.test.mjs +0 -219
  1989. package/template/.codex/skills/data-analytics/tests/recharts-config.test.mjs +0 -144
  1990. package/template/.codex/skills/data-analytics/tests/recharts-renderer.test.mjs +0 -11
  1991. package/template/.codex/skills/data-analytics/tests/rich-markdown.test.mjs +0 -54
  1992. package/template/.codex/skills/data-analytics/tests/widget-render-harness.html +0 -321
  1993. package/template/.codex/skills/data-analytics/tsconfig.json +0 -19
  1994. package/template/.codex/skills/data-analytics/vite.config.ts +0 -46
  1995. package/template/.codex/skills/grill-with-docs/SKILL.md +0 -20
  1996. package/template/.codex/skills/grill-with-docs/agents/openai.yaml +0 -5
  1997. package/template/.codex/skills/improve-codebase-architecture/SKILL.md +0 -75
  1998. package/template/.codex/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
  1999. package/template/.codex/skills/prototype/UI.md +0 -112
  2000. package/template/.codex/skills/setup-matt-pocock-skills/domain.md +0 -37
  2001. package/template/.codex/skills/to-questionnaire/SKILL.md +0 -55
  2002. package/template/.codex/skills/to-questionnaire/agents/openai.yaml +0 -5
  2003. package/template/.codex/skills/wait-what/SKILL.md +0 -7
  2004. package/template/.codex/skills/wait-what/agents/openai.yaml +0 -5
  2005. package/template/.codex/skills/yss-prototype-stage/assets/antd-authoring/package.json +0 -16
  2006. package/template/.codex/skills/yss-prototype-stage/assets/antd-authoring/pnpm-lock.yaml +0 -1678
  2007. package/template/.codex/skills/yss-prototype-stage/assets/antd-authoring/workbench.jsx +0 -23
  2008. package/template/.codex/skills/yss-prototype-stage/references/antd-component-catalog.json +0 -736
  2009. package/template/.codex/skills/yss-prototype-stage/references/antd-integration.md +0 -61
  2010. package/template/.codex/skills/yss-prototype-stage/scripts/build-antd-prototype.mjs +0 -71
  2011. package/template/.codex/skills/yss-prototype-stage/scripts/collect-antd-reference.mjs +0 -26
  2012. package/template/.cursor/skills/grill-with-docs/SKILL.md +0 -20
  2013. package/template/.cursor/skills/grill-with-docs/agents/openai.yaml +0 -5
  2014. package/template/.cursor/skills/improve-codebase-architecture/SKILL.md +0 -75
  2015. package/template/.cursor/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
  2016. package/template/.cursor/skills/prototype/UI.md +0 -112
  2017. package/template/.cursor/skills/setup-matt-pocock-skills/domain.md +0 -37
  2018. package/template/.cursor/skills/to-questionnaire/SKILL.md +0 -55
  2019. package/template/.cursor/skills/to-questionnaire/agents/openai.yaml +0 -5
  2020. package/template/.cursor/skills/wait-what/SKILL.md +0 -7
  2021. package/template/.cursor/skills/wait-what/agents/openai.yaml +0 -5
  2022. package/template/.cursor/skills/yss-prototype-stage/assets/antd-authoring/package.json +0 -16
  2023. package/template/.cursor/skills/yss-prototype-stage/assets/antd-authoring/pnpm-lock.yaml +0 -1678
  2024. package/template/.cursor/skills/yss-prototype-stage/assets/antd-authoring/workbench.jsx +0 -23
  2025. package/template/.cursor/skills/yss-prototype-stage/references/antd-component-catalog.json +0 -736
  2026. package/template/.cursor/skills/yss-prototype-stage/references/antd-integration.md +0 -61
  2027. package/template/.cursor/skills/yss-prototype-stage/scripts/build-antd-prototype.mjs +0 -71
  2028. package/template/.cursor/skills/yss-prototype-stage/scripts/collect-antd-reference.mjs +0 -26
  2029. package/template/.pi/skills/grill-with-docs/SKILL.md +0 -20
  2030. package/template/.pi/skills/grill-with-docs/agents/openai.yaml +0 -5
  2031. package/template/.pi/skills/improve-codebase-architecture/SKILL.md +0 -75
  2032. package/template/.pi/skills/improve-codebase-architecture/agents/openai.yaml +0 -5
  2033. package/template/.pi/skills/prototype/UI.md +0 -112
  2034. package/template/.pi/skills/setup-matt-pocock-skills/domain.md +0 -37
  2035. package/template/.pi/skills/to-questionnaire/SKILL.md +0 -55
  2036. package/template/.pi/skills/to-questionnaire/agents/openai.yaml +0 -5
  2037. package/template/.pi/skills/wait-what/SKILL.md +0 -7
  2038. package/template/.pi/skills/wait-what/agents/openai.yaml +0 -5
  2039. package/template/.pi/skills/yss-prototype-stage/assets/antd-authoring/package.json +0 -16
  2040. package/template/.pi/skills/yss-prototype-stage/assets/antd-authoring/pnpm-lock.yaml +0 -1678
  2041. package/template/.pi/skills/yss-prototype-stage/assets/antd-authoring/workbench.jsx +0 -23
  2042. package/template/.pi/skills/yss-prototype-stage/references/antd-component-catalog.json +0 -736
  2043. package/template/.pi/skills/yss-prototype-stage/references/antd-integration.md +0 -61
  2044. package/template/.pi/skills/yss-prototype-stage/scripts/build-antd-prototype.mjs +0 -71
  2045. package/template/.pi/skills/yss-prototype-stage/scripts/collect-antd-reference.mjs +0 -26
  2046. package/template/.template-spec/agents/domain.md +0 -31
  2047. /package/template/.agents/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
  2048. /package/template/.codex/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
  2049. /package/template/.cursor/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
  2050. /package/template/.pi/skills/{improve-codebase-architecture → codebase-design/references}/HTML-REPORT.md +0 -0
@@ -1,3666 +0,0 @@
1
- import { ArrowDown, ArrowUp, Boxes, Camera, ChartArea, ChartBar, ChartColumn, ChartColumnStacked, ChartLine, ChartNoAxesColumn, ChartNoAxesCombined, ChartScatter, ChartSpline, Check, ChevronDown, ChevronLeft, ChevronRight, Copy, Database, Ellipsis, Expand, Filter as FunnelIcon, FileDown, FileText, Globe, Pencil, Presentation, RefreshCw, Table2, Tally3, Trash2, X, } from "lucide-react";
2
- import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
3
- import { createPortal } from "react-dom";
4
- import { AnalyticsLayoutCanvas } from "./layout/AnalyticsLayoutCanvas";
5
- import { isChartType as sharedIsChartType } from "./charting/chart-compatibility";
6
- import { applyChartSpecOverride, chartEncoding, chartEncodingField, chartEncodingFields, chartEncodingLabel, chartHasEncodingSpec, chartSpecOverrideFromWidgetSpec, chartUsedFields, compatibleChartTypesFor, compatibleChartTypesForArtifactCard, withChartType } from "./charting/chart-app-helpers";
7
- import { ChartRenderer } from "./charting/ChartRenderer";
8
- import { RichMarkdown } from "./layout/RichMarkdown";
9
- import { copyElementAsImage, copyTextToClipboard, imageCopySuccessMessage, shouldOfferImageClipboardCopy, usePreparedImageExport } from "./imageExport";
10
- function resizeEditableTextarea(element) {
11
- if (!element)
12
- return;
13
- element.style.height = "auto";
14
- element.style.height = `${element.scrollHeight}px`;
15
- }
16
- function cloneSerializable(value) {
17
- return JSON.parse(JSON.stringify(value));
18
- }
19
- const DEFAULT_DASHBOARD_CARD_LAYOUT = "half";
20
- const DEFAULT_REPORT_CARD_LAYOUT = "full";
21
- const CARD_DRAG_CANCEL_SELECTOR = ".viz-card__no-drag, button, a, input, textarea, select, [contenteditable='true'], .rich-markdown-editor, [role='button'], [role='menu'], [role='menuitem'], [role='menuitemradio']";
22
- const CHART_FULLSCREEN_HEIGHT = 520;
23
- const TABLE_CARD_PAGE_SIZE = 15;
24
- const TABLE_COLUMN_DEFAULT_WIDTH = 144;
25
- const TABLE_COLUMN_DENSE_HORIZONTAL_PADDING = 16;
26
- const TABLE_COLUMN_HEADER_CHROME_WIDTH = 24;
27
- const TABLE_COLUMN_KEYBOARD_STEP = 24;
28
- const TABLE_COLUMN_MAX_WIDTH = 420;
29
- const TABLE_COLUMN_MIN_WIDTH = 88;
30
- const TABLE_COLUMN_NUMERIC_MAX_WIDTH = 136;
31
- const TABLE_COLUMN_SAMPLE_SIZE = 50;
32
- const TABLE_COLUMN_TEXT_MAX_WIDTH = 220;
33
- const TABLE_COLUMN_LONG_TEXT_MAX_WIDTH = 260;
34
- const EMPTY_ACCESS_ISSUES = [];
35
- const EMPTY_CARDS = [];
36
- const EMPTY_CHARTS = [];
37
- const EMPTY_FILTERS = [];
38
- const EMPTY_REPORT_BLOCKS = [];
39
- const EMPTY_TABLES = [];
40
- const KPI_COLUMN_BREAKPOINTS = [
41
- { minWidth: 760, columns: 3 },
42
- { minWidth: 520, columns: 2 },
43
- { minWidth: 392, columns: 2 }
44
- ];
45
- function getHeatmapFill(intensity) {
46
- const index = clamp(Math.floor(intensity * heatmapBlueScale.length), 0, heatmapBlueScale.length - 1);
47
- return heatmapBlueScale[index];
48
- }
49
- async function fetchJson(path, init) {
50
- const response = await fetch(path, { cache: "no-store", ...init });
51
- const text = await response.text();
52
- const payload = text ? JSON.parse(text) : {};
53
- if (!response.ok) {
54
- const message = typeof payload?.error === "string" ? payload.error : `Request failed: ${response.status}`;
55
- throw new Error(message);
56
- }
57
- return payload;
58
- }
59
- async function fetchOptionalJson(path, init) {
60
- try {
61
- return await fetchJson(path, init);
62
- }
63
- catch {
64
- return null;
65
- }
66
- }
67
- function asNumber(value) {
68
- if (typeof value === "number" && Number.isFinite(value))
69
- return value;
70
- if (typeof value === "string" && value.trim() !== "") {
71
- const numeric = Number(value.replace(/,/g, ""));
72
- if (Number.isFinite(numeric))
73
- return numeric;
74
- }
75
- return null;
76
- }
77
- function asFiniteNumber(value, fallback = 0) {
78
- if (typeof value === "number" && Number.isFinite(value))
79
- return value;
80
- if (typeof value === "string") {
81
- const numeric = Number(value);
82
- if (Number.isFinite(numeric))
83
- return numeric;
84
- }
85
- return fallback;
86
- }
87
- function clamp(value, min, max) {
88
- return Math.max(min, Math.min(max, value));
89
- }
90
- function formatValue(value, format = "compact") {
91
- const numeric = asNumber(value);
92
- if (numeric == null)
93
- return value == null ? "n/a" : String(value);
94
- if (format === "percent") {
95
- return new Intl.NumberFormat(undefined, {
96
- maximumFractionDigits: 1,
97
- style: "percent"
98
- }).format(numeric);
99
- }
100
- if (format === "currency") {
101
- return new Intl.NumberFormat(undefined, {
102
- currency: "USD",
103
- maximumFractionDigits: 2,
104
- notation: "compact",
105
- style: "currency"
106
- }).format(numeric);
107
- }
108
- if (format === "number") {
109
- return new Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }).format(numeric);
110
- }
111
- return new Intl.NumberFormat(undefined, {
112
- maximumFractionDigits: 2,
113
- notation: "compact"
114
- }).format(numeric);
115
- }
116
- function cardLabel(card) {
117
- return cardMetrics(card)[0]?.label ?? card.id;
118
- }
119
- function rowMatchesFilter(row, filter) {
120
- if (!filter)
121
- return true;
122
- return Object.entries(filter).every(([field, expected]) => String(row[field] ?? "") === String(expected ?? ""));
123
- }
124
- function movementDirection(value) {
125
- if (typeof value !== "string")
126
- return null;
127
- const trimmed = value.trim();
128
- if (!trimmed)
129
- return null;
130
- if (/^[+↑]/.test(trimmed))
131
- return "positive";
132
- if (/^[-−↓]/.test(trimmed))
133
- return "negative";
134
- return null;
135
- }
136
- function formatMetricValue(value, metric) {
137
- if (value == null || value === "")
138
- return null;
139
- const numeric = asNumber(value);
140
- const rendered = formatValue(value, metric.format);
141
- if (!metric.signed || numeric == null || numeric === 0)
142
- return rendered;
143
- return `${numeric > 0 ? "+" : ""}${rendered}`;
144
- }
145
- function metricMovementDirection(value, signed = false) {
146
- if (!signed)
147
- return null;
148
- const numeric = asNumber(value);
149
- if (numeric != null) {
150
- if (numeric > 0)
151
- return "positive";
152
- if (numeric < 0)
153
- return "negative";
154
- return "neutral";
155
- }
156
- return movementDirection(value);
157
- }
158
- function cardMetrics(card) {
159
- return Array.isArray(card.metrics) ? card.metrics : [];
160
- }
161
- function MetricInfoIcon({ className }) {
162
- return (<svg aria-hidden="true" className={className} fill="none" height="21" viewBox="0 0 21 21" width="21" xmlns="http://www.w3.org/2000/svg">
163
- <path d="M10.6 9.70459C11.0142 9.70461 11.35 10.0404 11.35 10.4546V13.7876C11.35 14.2018 11.0142 14.5376 10.6 14.5376C10.1858 14.5376 9.84998 14.2018 9.84998 13.7876V10.4546C9.84998 10.0404 10.1858 9.70459 10.6 9.70459Z" fill="currentColor"/>
164
- <path d="M10.6 6.2876C11.1292 6.28762 11.558 6.71732 11.558 7.24658C11.5578 7.77569 11.1291 8.20457 10.6 8.20459C10.0708 8.20459 9.64215 7.7757 9.64197 7.24658C9.64197 6.71731 10.0707 6.2876 10.6 6.2876Z" fill="currentColor"/>
165
- <path clipRule="evenodd" d="M10.6 2.53955C14.9713 2.53955 18.515 6.08326 18.515 10.4546C18.515 14.8259 14.9713 18.3696 10.6 18.3696C6.22864 18.3696 2.68494 14.8259 2.68494 10.4546C2.68494 6.08326 6.22864 2.53955 10.6 2.53955ZM10.6 3.86963C6.96318 3.86963 4.01501 6.81779 4.01501 10.4546C4.01501 14.0914 6.96318 17.0396 10.6 17.0396C14.2368 17.0396 17.1849 14.0914 17.1849 10.4546C17.1849 6.81779 14.2368 3.86963 10.6 3.86963Z" fill="currentColor" fillRule="evenodd"/>
166
- </svg>);
167
- }
168
- function MetricDescriptionPopover({ description, label }) {
169
- const tooltipId = useId();
170
- const buttonRef = useRef(null);
171
- const popoverRef = useRef(null);
172
- const [isOpen, setIsOpen] = useState(false);
173
- const [popoverStyle, setPopoverStyle] = useState(null);
174
- const updatePopoverPosition = useCallback(() => {
175
- if (typeof window === "undefined")
176
- return;
177
- const anchor = buttonRef.current?.getBoundingClientRect();
178
- if (!anchor)
179
- return;
180
- const margin = 12;
181
- const gap = 8;
182
- const maxWidth = Math.max(120, Math.min(320, window.innerWidth - margin * 2));
183
- const popoverRect = popoverRef.current?.getBoundingClientRect();
184
- const width = Math.min(popoverRect?.width ?? maxWidth, maxWidth);
185
- const height = popoverRect?.height ?? 0;
186
- let left = anchor.left + anchor.width / 2 - width / 2;
187
- left = clamp(left, margin, window.innerWidth - margin - width);
188
- let top = anchor.bottom + gap;
189
- if (height && top + height > window.innerHeight - margin && anchor.top - height - gap >= margin) {
190
- top = anchor.top - height - gap;
191
- }
192
- else if (height) {
193
- top = clamp(top, margin, window.innerHeight - margin - height);
194
- }
195
- setPopoverStyle((current) => {
196
- if (current?.left === left && current?.top === top && current?.maxWidth === maxWidth)
197
- return current;
198
- return { left, maxWidth, top };
199
- });
200
- }, []);
201
- useEffect(() => {
202
- if (!isOpen) {
203
- setPopoverStyle(null);
204
- return;
205
- }
206
- updatePopoverPosition();
207
- const frame = window.requestAnimationFrame(updatePopoverPosition);
208
- window.addEventListener("resize", updatePopoverPosition);
209
- window.addEventListener("scroll", updatePopoverPosition, true);
210
- return () => {
211
- window.cancelAnimationFrame(frame);
212
- window.removeEventListener("resize", updatePopoverPosition);
213
- window.removeEventListener("scroll", updatePopoverPosition, true);
214
- };
215
- }, [isOpen, updatePopoverPosition]);
216
- const renderedPopoverStyle = popoverStyle
217
- ? { left: popoverStyle.left, maxWidth: popoverStyle.maxWidth, top: popoverStyle.top }
218
- : { left: 0, maxWidth: "min(320px, calc(100vw - 24px))", top: 0, visibility: "hidden" };
219
- return (<span className="kpi-info-wrap" onBlur={() => setIsOpen(false)} onFocus={() => setIsOpen(true)} onMouseEnter={() => setIsOpen(true)} onMouseLeave={() => setIsOpen(false)}>
220
- <button aria-describedby={isOpen ? tooltipId : undefined} aria-label={`${label}: ${description}`} className="kpi-info" ref={buttonRef} type="button">
221
- <MetricInfoIcon className="kpi-info-icon"/>
222
- </button>
223
- {isOpen && typeof document !== "undefined" ? createPortal(<span className="kpi-info-popover" id={tooltipId} ref={popoverRef} role="tooltip" style={renderedPopoverStyle}>
224
- {description}
225
- </span>, document.body) : null}
226
- </span>);
227
- }
228
- function tableColumnFormat(column) {
229
- if (column.format)
230
- return column.format;
231
- return column.type === "currency" || column.type === "number" || column.type === "percent"
232
- ? column.type
233
- : undefined;
234
- }
235
- function tableColumnLooksLikeMovement(column) {
236
- return column.movement === true || column.semantic === "movement" || column.role === "movement";
237
- }
238
- function tableCellMovementClass(column, value) {
239
- if (!tableColumnLooksLikeMovement(column))
240
- return "";
241
- const numeric = asNumber(value);
242
- const direction = numeric == null ? movementDirection(value) : numeric > 0 ? "positive" : numeric < 0 ? "negative" : "neutral";
243
- if (!direction || direction === "neutral")
244
- return "";
245
- return `table-cell-movement table-cell-movement-${direction}`;
246
- }
247
- function formatTableDate(value) {
248
- if (value == null || value === "")
249
- return "";
250
- if (value instanceof Date && !Number.isNaN(value.getTime())) {
251
- return new Intl.DateTimeFormat(undefined, { dateStyle: "medium" }).format(value);
252
- }
253
- if (typeof value !== "string")
254
- return String(value);
255
- const trimmed = value.trim();
256
- const monthMatch = trimmed.match(/^(\d{4})-(\d{2})$/);
257
- if (monthMatch) {
258
- const [, yearValue, monthValue] = monthMatch;
259
- const date = new Date(Date.UTC(Number(yearValue), Number(monthValue) - 1, 1));
260
- if (!Number.isNaN(date.getTime())) {
261
- return new Intl.DateTimeFormat(undefined, {
262
- month: "short",
263
- timeZone: "UTC",
264
- year: "numeric"
265
- }).format(date);
266
- }
267
- }
268
- const dayMatch = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})(?:$|[T\s])/);
269
- if (dayMatch) {
270
- const [, yearValue, monthValue, dayValue] = dayMatch;
271
- const date = new Date(Date.UTC(Number(yearValue), Number(monthValue) - 1, Number(dayValue)));
272
- if (!Number.isNaN(date.getTime())) {
273
- return new Intl.DateTimeFormat(undefined, {
274
- day: "numeric",
275
- month: "short",
276
- timeZone: "UTC",
277
- year: "numeric"
278
- }).format(date);
279
- }
280
- }
281
- return trimmed;
282
- }
283
- function formatTableCellValue(column, value) {
284
- if (column.type === "date")
285
- return formatTableDate(value);
286
- const format = tableColumnFormat(column);
287
- const rendered = format ? formatValue(value, format) : String(value ?? "");
288
- if (!tableColumnLooksLikeMovement(column))
289
- return rendered;
290
- const numeric = asNumber(value);
291
- if (numeric == null || numeric === 0)
292
- return rendered;
293
- return `${numeric > 0 ? "+" : ""}${rendered}`;
294
- }
295
- function normalizedTableTextLength(value) {
296
- return String(value ?? "").replace(/\s+/g, " ").trim().length;
297
- }
298
- function percentileValue(values, percentile) {
299
- if (!values.length)
300
- return 0;
301
- const sorted = [...values].sort((a, b) => a - b);
302
- const index = clamp(Math.ceil(sorted.length * percentile) - 1, 0, sorted.length - 1);
303
- return sorted[index];
304
- }
305
- function isNumericTableColumn(column, rows) {
306
- if (tableColumnFormat(column))
307
- return true;
308
- let observed = false;
309
- for (const row of rows.slice(0, TABLE_COLUMN_SAMPLE_SIZE)) {
310
- const value = row[column.field];
311
- if (value == null || value === "")
312
- continue;
313
- observed = true;
314
- if (asNumber(value) == null)
315
- return false;
316
- }
317
- return observed;
318
- }
319
- function tableColumnDisplayText(column, row) {
320
- return formatTableCellValue(column, row[column.field]);
321
- }
322
- function estimateTableColumnWidth(column, rows, density) {
323
- const sampleRows = rows.slice(0, TABLE_COLUMN_SAMPLE_SIZE);
324
- const labelLength = normalizedTableTextLength(column.label);
325
- const cellLengths = sampleRows
326
- .map((row) => normalizedTableTextLength(tableColumnDisplayText(column, row)))
327
- .filter((length) => length > 0);
328
- const p90Length = percentileValue([labelLength, ...cellLengths], 0.9);
329
- const maxLength = Math.max(labelLength, ...cellLengths, 0);
330
- const columnKey = `${column.field} ${column.label}`.toLowerCase();
331
- const isLongTextColumn = /(comment|description|detail|explanation|insight|interpretation|note|reason|summary)/.test(columnKey)
332
- || maxLength > 34;
333
- const isNumericColumn = isNumericTableColumn(column, sampleRows);
334
- const isDateColumn = /(date|day|month|quarter|week)/.test(columnKey);
335
- const horizontalPadding = TABLE_COLUMN_HEADER_CHROME_WIDTH + (density === "dense" ? TABLE_COLUMN_DENSE_HORIZONTAL_PADDING : 0);
336
- const charWidth = isNumericColumn ? 7.2 : 7.4;
337
- const targetLength = isLongTextColumn
338
- ? Math.min(Math.max(labelLength + 4, p90Length), 44)
339
- : Math.max(labelLength, p90Length);
340
- const measuredWidth = Math.ceil(targetLength * charWidth + horizontalPadding);
341
- if (isNumericColumn) {
342
- const minWidth = tableColumnFormat(column) === "percent" ? 96 : 108;
343
- return clamp(measuredWidth, minWidth, TABLE_COLUMN_NUMERIC_MAX_WIDTH);
344
- }
345
- if (isDateColumn) {
346
- return clamp(measuredWidth, 116, 156);
347
- }
348
- if (isLongTextColumn) {
349
- return clamp(measuredWidth, 220, TABLE_COLUMN_LONG_TEXT_MAX_WIDTH);
350
- }
351
- return clamp(measuredWidth, density === "dense" ? 124 : 112, TABLE_COLUMN_TEXT_MAX_WIDTH);
352
- }
353
- function estimateTableColumnWidths(table, rows, density) {
354
- return Object.fromEntries(table.columns.map((column) => [
355
- column.field,
356
- estimateTableColumnWidth(column, rows, density)
357
- ]));
358
- }
359
- function formatDate(value) {
360
- if (!value)
361
- return "Unknown";
362
- const date = new Date(value);
363
- if (Number.isNaN(date.getTime()))
364
- return value;
365
- return new Intl.DateTimeFormat(undefined, {
366
- dateStyle: "medium",
367
- timeStyle: "short"
368
- }).format(date);
369
- }
370
- function snapshotStatusLabel(status) {
371
- if (!status || status === "ready")
372
- return null;
373
- if (status === "fixture")
374
- return "Fixture data";
375
- if (status === "partial")
376
- return null;
377
- return "Blocked snapshot";
378
- }
379
- function getRows(snapshot, dataset) {
380
- return snapshot?.datasets?.[dataset] ?? [];
381
- }
382
- function asArray(value) {
383
- return Array.isArray(value) ? value : [];
384
- }
385
- function asRecord(value) {
386
- return value && typeof value === "object" && !Array.isArray(value)
387
- ? value
388
- : {};
389
- }
390
- function normalizeManifest(rawManifest) {
391
- const manifest = asRecord(rawManifest);
392
- return {
393
- ...manifest,
394
- version: 1,
395
- title: typeof manifest.title === "string" ? manifest.title : "Data Analytics artifact",
396
- generatedAt: typeof manifest.generatedAt === "string" ? manifest.generatedAt : "",
397
- filters: asArray(manifest.filters).map((rawFilter) => {
398
- const filter = asRecord(rawFilter);
399
- return {
400
- ...filter,
401
- targets: asArray(filter.targets)
402
- };
403
- }),
404
- cards: asArray(manifest.cards).map((rawCard) => asRecord(rawCard)),
405
- charts: asArray(manifest.charts).map((rawChart) => {
406
- const chart = asRecord(rawChart);
407
- return {
408
- ...chart,
409
- referenceLines: asArray(chart.referenceLines)
410
- };
411
- }),
412
- tables: asArray(manifest.tables).map((rawTable) => {
413
- const table = asRecord(rawTable);
414
- return {
415
- ...table,
416
- columns: asArray(table.columns)
417
- };
418
- }),
419
- sources: asArray(manifest.sources).map((rawSource) => asRecord(rawSource)),
420
- blocks: asArray(manifest.blocks).map((rawBlock) => {
421
- const block = asRecord(rawBlock);
422
- return {
423
- ...block,
424
- cardIds: asArray(block.cardIds)
425
- };
426
- })
427
- };
428
- }
429
- function normalizeSnapshot(rawSnapshot) {
430
- const snapshot = asRecord(rawSnapshot);
431
- const datasets = {};
432
- const rawDatasets = asRecord(snapshot.datasets);
433
- for (const [dataset, rows] of Object.entries(rawDatasets)) {
434
- datasets[dataset] = asArray(rows).filter((row) => Boolean(row) && typeof row === "object" && !Array.isArray(row));
435
- }
436
- return {
437
- ...snapshot,
438
- version: 1,
439
- generatedAt: typeof snapshot.generatedAt === "string" ? snapshot.generatedAt : "",
440
- datasets,
441
- accessIssues: asArray(snapshot.accessIssues)
442
- };
443
- }
444
- function filterTargets(filter) {
445
- const targets = [{ dataset: filter.dataset, field: filter.field }];
446
- for (const target of filter.targets ?? []) {
447
- targets.push({ dataset: target.dataset, field: target.field ?? filter.field });
448
- }
449
- const seen = new Set();
450
- return targets.filter((target) => {
451
- const key = `${target.dataset}\u0001${target.field}`;
452
- if (seen.has(key))
453
- return false;
454
- seen.add(key);
455
- return true;
456
- });
457
- }
458
- function filterFieldForDataset(filter, dataset) {
459
- return filterTargets(filter).find((target) => target.dataset === dataset)?.field ?? null;
460
- }
461
- function dashboardSurfaceDatasets(cards, charts, tables) {
462
- return new Set([...cards, ...charts, ...tables]
463
- .map((surface) => surface.dataset)
464
- .filter((dataset) => Boolean(dataset)));
465
- }
466
- function isGlobalFilter(filter, cards, charts, tables) {
467
- const requiredDatasets = dashboardSurfaceDatasets(cards, charts, tables);
468
- if (requiredDatasets.size <= 1)
469
- return true;
470
- const targetDatasets = new Set(filterTargets(filter).map((target) => target.dataset));
471
- return [...requiredDatasets].every((dataset) => targetDatasets.has(dataset));
472
- }
473
- function getGlobalFilters(filters, cards, charts, tables) {
474
- return filters.filter((filter) => isGlobalFilter(filter, cards, charts, tables));
475
- }
476
- function filterRowsForDataset(rows, dataset, filters, selectedFilters, usedFields = []) {
477
- const usedFieldSet = new Set(usedFields.filter(Boolean));
478
- const explicitAllFields = new Set(filters
479
- .map((filter) => {
480
- const field = filterFieldForDataset(filter, dataset);
481
- const selected = selectedFilters[filter.id] ?? filter.defaultValue ?? "all";
482
- return field && selected === "all" && rows.some((row) => String(row[field] ?? "") === "all")
483
- ? field
484
- : null;
485
- })
486
- .filter((field) => Boolean(field)));
487
- const filteredRows = rows.filter((row) => filters.every((filter) => {
488
- const field = filterFieldForDataset(filter, dataset);
489
- if (!field)
490
- return true;
491
- const selected = selectedFilters[filter.id] ?? filter.defaultValue ?? "all";
492
- if (selected === "all") {
493
- return !explicitAllFields.has(field) || String(row[field] ?? "") === "all";
494
- }
495
- return String(row[field] ?? "") === selected;
496
- }));
497
- const aggregateFields = Object.keys(rows[0] ?? {}).filter((field) => {
498
- if (usedFieldSet.has(field))
499
- return false;
500
- let hasAggregate = false;
501
- let hasBreakdown = false;
502
- for (const row of filteredRows) {
503
- const value = String(row[field] ?? "");
504
- if (value === "all")
505
- hasAggregate = true;
506
- else if (value)
507
- hasBreakdown = true;
508
- if (hasAggregate && hasBreakdown)
509
- return true;
510
- }
511
- return false;
512
- });
513
- if (!aggregateFields.length)
514
- return filteredRows;
515
- const aggregateRows = filteredRows.filter((row) => aggregateFields.every((field) => String(row[field] ?? "") === "all"));
516
- return aggregateRows.length ? aggregateRows : filteredRows;
517
- }
518
- function DashboardShell({ children, detailMode = false, isEditMode = false, surface }) {
519
- return (<main className={`dashboard-shell ${surface === "report" ? "report-shell" : ""} ${detailMode ? "chart-detail-shell" : ""} ${isEditMode ? "is-app-editing" : ""}`.trim()} data-edit-mode={isEditMode ? "true" : "false"}>
520
- {children}
521
- </main>);
522
- }
523
- function dashboardCardLayout(layout) {
524
- return layout ?? DEFAULT_DASHBOARD_CARD_LAYOUT;
525
- }
526
- function reportCardLayout(layout) {
527
- return layout ?? DEFAULT_REPORT_CARD_LAYOUT;
528
- }
529
- function contentLayoutKey(manifest) {
530
- if (!manifest)
531
- return null;
532
- const base = `${manifest.title}:${manifest.generatedAt}`;
533
- return `datascience-dashboard:content-layout:${base}`;
534
- }
535
- function chartTextKey(manifest) {
536
- if (!manifest)
537
- return null;
538
- const base = `${manifest.title}:${manifest.generatedAt}`;
539
- return `datascience-dashboard:chart-text:${base}`;
540
- }
541
- function chartTypeKey(manifest) {
542
- if (!manifest)
543
- return null;
544
- const base = `${manifest.title}:${manifest.generatedAt}`;
545
- return `datascience-${manifest.surface ?? "dashboard"}:chart-type:${base}`;
546
- }
547
- function chartSpecKey(manifest) {
548
- if (!manifest)
549
- return null;
550
- const base = `${manifest.title}:${manifest.generatedAt}`;
551
- return `datascience-${manifest.surface ?? "dashboard"}:chart-spec:${base}`;
552
- }
553
- function pageTitleTextKey(manifest) {
554
- if (!manifest)
555
- return null;
556
- const base = `${manifest.title}:${manifest.generatedAt}`;
557
- return `datascience-${manifest.surface ?? "dashboard"}:page-title:${base}`;
558
- }
559
- function tableTextKey(manifest) {
560
- if (!manifest)
561
- return null;
562
- const base = `${manifest.title}:${manifest.generatedAt}`;
563
- return `datascience-${manifest.surface ?? "dashboard"}:table-text:${base}`;
564
- }
565
- function storageKeyHash(value) {
566
- let hash = 2166136261;
567
- for (let index = 0; index < value.length; index += 1) {
568
- hash ^= value.charCodeAt(index);
569
- hash = Math.imul(hash, 16777619);
570
- }
571
- return (hash >>> 0).toString(36);
572
- }
573
- function blockTextKey(manifest) {
574
- if (!manifest)
575
- return null;
576
- const base = `${manifest.title}:${manifest.generatedAt}`;
577
- const blockSignature = (manifest.blocks ?? [])
578
- .map((block) => `${block.id}:${block.type}:${typeof block.body === "string" ? storageKeyHash(block.body) : ""}`)
579
- .join(",");
580
- return `datascience-report:block-text:${base}:${storageKeyHash(blockSignature)}`;
581
- }
582
- function deletedReportBlocksKey(manifest) {
583
- if (!manifest)
584
- return null;
585
- const base = `${manifest.title}:${manifest.generatedAt}`;
586
- const blockSignature = (manifest.blocks ?? [])
587
- .map((block) => block.id)
588
- .join(",");
589
- return `datascience-report:deleted-blocks:${base}:${blockSignature}`;
590
- }
591
- function tableColumnWidthKey(manifest) {
592
- if (!manifest)
593
- return null;
594
- const base = `${manifest.title}:${manifest.generatedAt}`;
595
- const surface = manifest.surface ?? "dashboard";
596
- const tableSignature = (manifest.tables ?? [])
597
- .map((table) => `${table.id}:${table.columns.map((column) => column.field).join("|")}`)
598
- .join(",");
599
- return `datascience-${surface}:table-column-widths:${base}:${tableSignature}`;
600
- }
601
- function reportContentLayoutKey(manifest) {
602
- if (!manifest)
603
- return null;
604
- const base = `${manifest.title}:${manifest.generatedAt}`;
605
- const blockSignature = (manifest.blocks ?? [])
606
- .map((block) => `${block.id}:${reportCardLayout(block.layout)}`)
607
- .join(",");
608
- return `datascience-report:content-layout:v3:${base}:${blockSignature}`;
609
- }
610
- function sourceForChart(chart, sources) {
611
- if (chart?.source && typeof chart.source === "object")
612
- return chart.source;
613
- return sources.find((source) => source.id === chart.sourceId) ?? null;
614
- }
615
- function sourceForTable(table, sources) {
616
- if (table?.source && typeof table.source === "object")
617
- return table.source;
618
- return sources.find((source) => source.id === table.sourceId) ?? null;
619
- }
620
- function sourceQueryFromChartSpec(chart) {
621
- return chart?.source?.query ?? null;
622
- }
623
- function sourceQueryFromSourceSpec(source) {
624
- if (!source)
625
- return null;
626
- return source.query ?? null;
627
- }
628
- function queryTextFromSourceQuery(sourceQuery) {
629
- return (sourceQuery?.sql ?? "").trim();
630
- }
631
- function accessIssueForChart(chart, issues) {
632
- return (issues.find((issue) => issue.dataset === chart.dataset) ??
633
- issues.find((issue) => issue.sourceId && issue.sourceId === chart.sourceId) ??
634
- null);
635
- }
636
- function activeFilterSummary(filters, selectedFilters) {
637
- const active = filters
638
- .map((filter) => {
639
- const value = selectedFilters[filter.id] ?? filter.defaultValue ?? "all";
640
- return value === "all" ? null : `${filter.label}: ${value}`;
641
- })
642
- .filter(Boolean);
643
- return active.length ? active.join(", ") : "None";
644
- }
645
- function stringListFromValue(value) {
646
- if (Array.isArray(value)) {
647
- return value
648
- .map((item) => {
649
- if (item && typeof item === "object") {
650
- const label = item.label ?? item.name ?? item.table ?? item.field ?? item.metric ?? item.id;
651
- const detail = item.description ?? item.definition ?? item.value ?? item.expression;
652
- return label && detail ? `${label}: ${detail}` : label ?? detail;
653
- }
654
- return item;
655
- })
656
- .map((item) => String(item ?? "").trim())
657
- .filter(Boolean);
658
- }
659
- if (value && typeof value === "object") {
660
- return Object.entries(value)
661
- .map(([key, item]) => `${key}: ${item}`)
662
- .map((item) => item.trim())
663
- .filter(Boolean);
664
- }
665
- const textValue = String(value ?? "").trim();
666
- return textValue ? [textValue] : [];
667
- }
668
- function firstStringList(objects, keys) {
669
- for (const object of objects) {
670
- if (!object)
671
- continue;
672
- for (const key of keys) {
673
- const values = stringListFromValue(object[key]);
674
- if (values.length)
675
- return values;
676
- }
677
- }
678
- return [];
679
- }
680
- function isLikelySourceTableName(value) {
681
- const tableName = String(value ?? "").trim().replace(/^[`"\[]|[`"\]]$/g, "");
682
- return /^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+){1,3}$/.test(tableName);
683
- }
684
- function sourceTableNamesFromMetadata(objects) {
685
- const values = firstStringList(objects, ["tables_used", "tablesUsed", "source_tables", "sourceTables", "tables"]);
686
- return values.filter(isLikelySourceTableName);
687
- }
688
- function extractTablesFromQuery(queryText) {
689
- const tables = [];
690
- const seen = new Set();
691
- const pattern = /\b(?:from|join)\s+([`"\[]?[\w.-]+(?:\.[\w.-]+){0,3}[`"\]]?)/gi;
692
- let match;
693
- while ((match = pattern.exec(queryText ?? ""))) {
694
- const table = match[1].replace(/^[`"\[]|[`"\]]$/g, "");
695
- const normalized = table.toLowerCase();
696
- if (!table || seen.has(normalized))
697
- continue;
698
- seen.add(normalized);
699
- tables.push(table);
700
- }
701
- return tables;
702
- }
703
- function sourceBuildDetails({ activeFilters, columns = [], dataset, metrics = [], source, sourceQuery, snapshot }) {
704
- const queryText = queryTextFromSourceQuery(sourceQueryFromSourceSpec(source)) || queryTextFromSourceQuery(sourceQuery) || "";
705
- const metadataObjects = [source, sourceQueryFromSourceSpec(source), sourceQuery].filter(Boolean);
706
- const explicitTables = sourceTableNamesFromMetadata(metadataObjects);
707
- const inferredTables = extractTablesFromQuery(queryText);
708
- const tables = explicitTables.length ? explicitTables : inferredTables;
709
- const filters = firstStringList(metadataObjects, [
710
- "filters",
711
- "filter_descriptions",
712
- "filterDescriptions",
713
- "filter_description",
714
- "filterDescription",
715
- ]);
716
- const metricDefinitions = firstStringList(metadataObjects, [
717
- "metric_definitions",
718
- "metricDefinitions",
719
- "metrics_definition",
720
- "metricDefinition",
721
- ]);
722
- const fallbackMetrics = metricDefinitions.length
723
- ? metricDefinitions
724
- : metrics.length
725
- ? metrics.map((metric) => `${metric.label}: displayed from ${metric.field}`)
726
- : columns
727
- .filter((column) => ["number", "percent", "currency"].includes(column.format ?? column.type ?? ""))
728
- .map((column) => `${column.label ?? column.field}: displayed from ${column.field}`)
729
- .slice(0, 6);
730
- const filterRows = filters.length ? filters : activeFilters && activeFilters !== "None" ? [activeFilters] : ["None declared"];
731
- const tableRows = tables.length ? tables : ["Not declared"];
732
- const snapshotValue = sourceQuery?.executed_at ?? sourceQueryFromSourceSpec(source)?.executed_at ?? snapshot?.generatedAt ?? "Not declared";
733
- const primarySource = tableRows[0] === "Not declared" ? dataset ?? "reviewed rows" : tableRows[0];
734
- const summary = `This block uses ${primarySource} for dataset ${dataset ?? "unknown"}.${filterRows[0] !== "None declared" ? ` Filters: ${filterRows.slice(0, 2).join("; ")}.` : ""} Use the source query below to inspect the exact logic.`;
735
- return {
736
- dataset: dataset ?? "Not declared",
737
- fields: columns
738
- .map((column) => column.field ?? column.key ?? column.label)
739
- .filter(Boolean),
740
- filters: filterRows,
741
- metricDefinitions: fallbackMetrics.length ? fallbackMetrics : ["Displayed directly from source columns"],
742
- snapshot: snapshotValue,
743
- summary,
744
- tables: tableRows
745
- };
746
- }
747
- function detailText(values, fallback = "Not declared") {
748
- const items = Array.isArray(values) ? values.filter(Boolean) : [values].filter(Boolean);
749
- return items.length ? items.join("; ") : fallback;
750
- }
751
- function detailList(values, fallback = "Not declared") {
752
- const items = Array.isArray(values) ? values.filter(Boolean) : [values].filter(Boolean);
753
- if (!items.length)
754
- return fallback;
755
- return (<div className="source-detail-list">
756
- {items.map((item, index) => <div className="source-detail-list-item" key={`${index}-${item}`}>
757
- {item}
758
- </div>)}
759
- </div>);
760
- }
761
- function compareTableValues(a, b, field, direction) {
762
- const aValue = a[field];
763
- const bValue = b[field];
764
- if (aValue == null && bValue == null)
765
- return 0;
766
- if (aValue == null)
767
- return direction === "asc" ? 1 : -1;
768
- if (bValue == null)
769
- return direction === "asc" ? -1 : 1;
770
- let result = 0;
771
- if (typeof aValue === "number" && typeof bValue === "number") {
772
- result = aValue - bValue;
773
- }
774
- else {
775
- result = String(aValue).localeCompare(String(bValue), undefined, {
776
- numeric: true,
777
- sensitivity: "base"
778
- });
779
- }
780
- return direction === "asc" ? result : -result;
781
- }
782
- function MetricBadge({ metric, row }) {
783
- const value = row[metric.field];
784
- const renderedValue = formatMetricValue(value, metric);
785
- if (!renderedValue)
786
- return null;
787
- const direction = metricMovementDirection(value, metric.signed === true);
788
- return (<div className={`metric-badge ${direction ?? "neutral"}`}>
789
- <span className="metric-badge-label">{metric.label}</span>
790
- <span className="metric-badge-value">{renderedValue}</span>
791
- </div>);
792
- }
793
- function KpiCard({ card, filters, selectedFilters, snapshot }) {
794
- const metrics = cardMetrics(card);
795
- const [primaryMetric, ...supportingMetrics] = metrics;
796
- const rows = filterRowsForDataset(getRows(snapshot, card.dataset), card.dataset, filters, selectedFilters, metrics.map((metric) => metric.field));
797
- const row = rows.find((candidate) => rowMatchesFilter(candidate, card.filter)) ?? {};
798
- const label = cardLabel(card);
799
- const description = card.description?.trim();
800
- return (<section className="kpi-card">
801
- <div className="kpi-label-row">
802
- <div className="kpi-label">{label}</div>
803
- {description ? <MetricDescriptionPopover description={description} label={label}/> : null}
804
- </div>
805
- <div className="kpi-value">{primaryMetric ? formatValue(row[primaryMetric.field], primaryMetric.format) : "—"}</div>
806
- {supportingMetrics.length ? (<div className="metric-badge-row">
807
- {supportingMetrics.map((metric) => (<MetricBadge key={`${metric.field}:${metric.label}`} metric={metric} row={row}/>))}
808
- </div>) : null}
809
- </section>);
810
- }
811
- function getKpiColumnCount(width, cardCount) {
812
- const breakpoint = KPI_COLUMN_BREAKPOINTS.find((item) => width >= item.minWidth);
813
- return Math.max(1, Math.min(cardCount, breakpoint?.columns ?? 1));
814
- }
815
- function useMeasuredElementSize() {
816
- const ref = useRef(null);
817
- const [size, setSize] = useState({ height: 0, width: 0 });
818
- useEffect(() => {
819
- const element = ref.current;
820
- if (!element)
821
- return;
822
- let frame = 0;
823
- const updateWidth = () => {
824
- window.cancelAnimationFrame(frame);
825
- frame = window.requestAnimationFrame(() => {
826
- const rect = element.getBoundingClientRect();
827
- setSize({
828
- height: Math.floor(rect.height),
829
- width: Math.floor(rect.width)
830
- });
831
- });
832
- };
833
- updateWidth();
834
- const observer = new ResizeObserver(updateWidth);
835
- observer.observe(element);
836
- window.addEventListener("resize", updateWidth);
837
- return () => {
838
- window.cancelAnimationFrame(frame);
839
- observer.disconnect();
840
- window.removeEventListener("resize", updateWidth);
841
- };
842
- }, []);
843
- return [ref, size];
844
- }
845
- function KpiStrip({ cards, filters, selectedFilters, snapshot }) {
846
- const [stripRef, stripSize] = useMeasuredElementSize();
847
- const fallbackWidth = typeof window === "undefined" ? 0 : window.innerWidth;
848
- const columns = getKpiColumnCount(stripSize.width || fallbackWidth, cards.length);
849
- const placeholderCount = (columns - (cards.length % columns)) % columns;
850
- const stripStyle = { "--kpi-columns": columns };
851
- if (!cards.length)
852
- return null;
853
- return (<section className={`kpi-strip kpi-columns-${columns}`} style={stripStyle} aria-label="Key metrics" ref={stripRef}>
854
- {cards.map((card) => (<KpiCard card={card} filters={filters} key={card.id} selectedFilters={selectedFilters} snapshot={snapshot}/>))}
855
- {Array.from({ length: placeholderCount }, (_, index) => (<div aria-hidden="true" className="kpi-card kpi-card-placeholder" key={`kpi-placeholder-${index}`}/>))}
856
- </section>);
857
- }
858
- const MENU_CLOSE_ANIMATION_MS = 100;
859
- const NARROW_FIXED_MENU_QUERY = "(max-width: 560px)";
860
- function useDashboardMenu(isOpen, onOpenChange) {
861
- const menuButtonRef = useRef(null);
862
- const menuRef = useRef(null);
863
- const isOpenRef = useRef(isOpen);
864
- const [shouldRenderMenu, setShouldRenderMenu] = useState(isOpen);
865
- const [menuMotionClass, setMenuMotionClass] = useState("opening");
866
- const [fixedMenuStyle, setFixedMenuStyle] = useState(undefined);
867
- useEffect(() => {
868
- isOpenRef.current = isOpen;
869
- }, [isOpen]);
870
- const updateFixedMenuStyle = useCallback(() => {
871
- if (typeof window === "undefined") {
872
- return;
873
- }
874
- if (!window.matchMedia(NARROW_FIXED_MENU_QUERY).matches) {
875
- setFixedMenuStyle(undefined);
876
- return;
877
- }
878
- const anchor = menuButtonRef.current?.getBoundingClientRect();
879
- if (!anchor) {
880
- return;
881
- }
882
- const menuSurface = menuRef.current?.matches?.('[role="menu"]')
883
- ? menuRef.current
884
- : menuRef.current?.querySelector?.('[role="menu"]');
885
- const margin = 12;
886
- const gap = 6;
887
- const surfaceHeight = menuSurface?.getBoundingClientRect?.().height ?? 0;
888
- let top = anchor.bottom + gap;
889
- if (surfaceHeight && top + surfaceHeight > window.innerHeight - margin && anchor.top - surfaceHeight - gap >= margin) {
890
- top = anchor.top - surfaceHeight - gap;
891
- }
892
- else if (surfaceHeight) {
893
- top = clamp(top, margin, window.innerHeight - margin - surfaceHeight);
894
- }
895
- else {
896
- top = clamp(top, margin, window.innerHeight - margin);
897
- }
898
- setFixedMenuStyle((current) => {
899
- if (current?.top === top)
900
- return current;
901
- return { top };
902
- });
903
- }, []);
904
- function menuItems() {
905
- return Array.from(menuRef.current?.querySelectorAll('[role="menuitem"], [role="menuitemradio"]') ?? []).filter((item) => !item.disabled);
906
- }
907
- function focusMenuItem(position) {
908
- window.requestAnimationFrame(() => {
909
- const items = menuItems();
910
- if (!items.length)
911
- return;
912
- const index = position === "first"
913
- ? 0
914
- : position === "last"
915
- ? items.length - 1
916
- : Math.max(0, Math.min(items.length - 1, position));
917
- items[index]?.focus();
918
- });
919
- }
920
- function openMenu() {
921
- setShouldRenderMenu(true);
922
- setMenuMotionClass("opening");
923
- onOpenChange(true);
924
- }
925
- function closeMenu() {
926
- onOpenChange(false);
927
- }
928
- function setMenuOpen(nextIsOpen) {
929
- if (nextIsOpen) {
930
- openMenu();
931
- return;
932
- }
933
- closeMenu();
934
- }
935
- function toggleMenu() {
936
- const nextIsOpen = !isOpenRef.current;
937
- setMenuOpen(nextIsOpen);
938
- return nextIsOpen;
939
- }
940
- useEffect(() => {
941
- if (isOpen) {
942
- setShouldRenderMenu(true);
943
- setMenuMotionClass("opening");
944
- return;
945
- }
946
- if (!shouldRenderMenu)
947
- return;
948
- setMenuMotionClass("closing");
949
- const closeTimer = window.setTimeout(() => {
950
- setShouldRenderMenu(false);
951
- }, MENU_CLOSE_ANIMATION_MS);
952
- return () => {
953
- window.clearTimeout(closeTimer);
954
- };
955
- }, [isOpen, shouldRenderMenu]);
956
- useLayoutEffect(() => {
957
- if (!shouldRenderMenu) {
958
- setFixedMenuStyle(undefined);
959
- return;
960
- }
961
- updateFixedMenuStyle();
962
- const frame = window.requestAnimationFrame(updateFixedMenuStyle);
963
- window.addEventListener("resize", updateFixedMenuStyle);
964
- window.addEventListener("scroll", updateFixedMenuStyle, true);
965
- return () => {
966
- window.cancelAnimationFrame(frame);
967
- window.removeEventListener("resize", updateFixedMenuStyle);
968
- window.removeEventListener("scroll", updateFixedMenuStyle, true);
969
- };
970
- }, [shouldRenderMenu, updateFixedMenuStyle]);
971
- useEffect(() => {
972
- if (!isOpen)
973
- return;
974
- function handlePointerDown(event) {
975
- const target = event.target;
976
- if (!menuRef.current?.contains(target) && !menuButtonRef.current?.contains(target)) {
977
- closeMenu();
978
- }
979
- }
980
- function handleKeyDown(event) {
981
- if (event.key === "Escape") {
982
- closeMenu();
983
- menuButtonRef.current?.focus();
984
- }
985
- }
986
- document.addEventListener("pointerdown", handlePointerDown);
987
- document.addEventListener("keydown", handleKeyDown);
988
- return () => {
989
- document.removeEventListener("pointerdown", handlePointerDown);
990
- document.removeEventListener("keydown", handleKeyDown);
991
- };
992
- }, [isOpen, onOpenChange]);
993
- return {
994
- closeMenu,
995
- fixedMenuStyle,
996
- handleMenuButtonKeyDown: (event) => {
997
- if (event.key === "ArrowDown" || event.key === "ArrowUp") {
998
- event.preventDefault();
999
- openMenu();
1000
- focusMenuItem(event.key === "ArrowDown" ? "first" : "last");
1001
- }
1002
- },
1003
- handleMenuKeyDown: (event) => {
1004
- if (event.key !== "ArrowDown" &&
1005
- event.key !== "ArrowUp" &&
1006
- event.key !== "Home" &&
1007
- event.key !== "End" &&
1008
- event.key !== "Escape") {
1009
- return;
1010
- }
1011
- event.preventDefault();
1012
- if (event.key === "Escape") {
1013
- closeMenu();
1014
- menuButtonRef.current?.focus();
1015
- return;
1016
- }
1017
- const items = menuItems();
1018
- if (!items.length)
1019
- return;
1020
- const activeIndex = items.findIndex((item) => item === document.activeElement);
1021
- if (event.key === "Home") {
1022
- focusMenuItem("first");
1023
- return;
1024
- }
1025
- if (event.key === "End") {
1026
- focusMenuItem("last");
1027
- return;
1028
- }
1029
- const offset = event.key === "ArrowDown" ? 1 : -1;
1030
- const nextIndex = activeIndex === -1
1031
- ? (event.key === "ArrowDown" ? 0 : items.length - 1)
1032
- : (activeIndex + offset + items.length) % items.length;
1033
- focusMenuItem(nextIndex);
1034
- },
1035
- menuButtonRef,
1036
- menuMotionClass,
1037
- menuRef,
1038
- toggleMenu,
1039
- shouldRenderMenu
1040
- };
1041
- }
1042
- function FilterMenu({ label, onChange, options, value }) {
1043
- const [isOpen, setIsOpen] = useState(false);
1044
- const { closeMenu, handleMenuButtonKeyDown, handleMenuKeyDown, menuButtonRef, menuMotionClass, menuRef, toggleMenu, shouldRenderMenu } = useDashboardMenu(isOpen, setIsOpen);
1045
- const selectedOption = options.find((option) => option.value === value) ?? options[0];
1046
- return (<div className="filter-menu" ref={menuRef}>
1047
- <button aria-expanded={isOpen} aria-haspopup="menu" className="filter-menu-button" onClick={toggleMenu} onKeyDown={handleMenuButtonKeyDown} ref={menuButtonRef} type="button">
1048
- <span className="filter-menu-label">{label}</span>
1049
- <span className="filter-menu-value">{selectedOption?.label ?? value}</span>
1050
- <ChevronDown aria-hidden="true" size={14} strokeWidth={2}/>
1051
- </button>
1052
- {shouldRenderMenu ? (<div className={`filter-menu-list menu-surface ${menuMotionClass}`} onKeyDown={handleMenuKeyDown} role="menu">
1053
- {options.map((option) => {
1054
- const isSelected = option.value === value;
1055
- return (<button aria-checked={isSelected} className="filter-menu-item" key={option.value} onClick={() => {
1056
- onChange(option.value);
1057
- closeMenu();
1058
- }} role="menuitemradio" type="button">
1059
- <span>{option.label}</span>
1060
- {isSelected ? <Check aria-hidden="true" size={14} strokeWidth={2}/> : null}
1061
- </button>);
1062
- })}
1063
- </div>) : null}
1064
- </div>);
1065
- }
1066
- function FilterToolbar({ filters, snapshot, selectedFilters, onChange }) {
1067
- if (!filters.length)
1068
- return null;
1069
- return (<div className="filter-toolbar" aria-label="Analytics filters">
1070
- <div className="filter-group">
1071
- {filters.map((filter) => {
1072
- const options = Array.from(new Set(getRows(snapshot, filter.dataset).map((row) => String(row[filter.field] ?? ""))))
1073
- .filter(Boolean)
1074
- .sort();
1075
- const filterOptions = [
1076
- ...(filter.includeAll === false ? [] : [{ label: "All", value: "all" }]),
1077
- ...options.map((option) => ({ label: option, value: option }))
1078
- ];
1079
- const value = selectedFilters[filter.id] ?? filter.defaultValue ?? "all";
1080
- return (<FilterMenu key={filter.id} label={filter.label} onChange={(nextValue) => onChange({ ...selectedFilters, [filter.id]: nextValue })} options={filterOptions} value={value}/>);
1081
- })}
1082
- </div>
1083
- </div>);
1084
- }
1085
- function PanelHeader({ action, children, title, subtitle, titleRowClassName, titleRowProps }) {
1086
- return (<div className="panel-header">
1087
- <div {...titleRowProps} className={`panel-title-row ${titleRowClassName ?? ""} ${titleRowProps?.className ?? ""}`.trim()}>
1088
- {children ?? (<div>
1089
- <h2>{title}</h2>
1090
- {subtitle ? <p>{subtitle}</p> : null}
1091
- </div>)}
1092
- </div>
1093
- {action}
1094
- </div>);
1095
- }
1096
- function EditablePageTitle({ ariaLabel, isEditMode, onChange, onRequestEditMode, placeholder, readOnly = false, title }) {
1097
- const [isEditing, setIsEditing] = useState(false);
1098
- const textareaRef = useRef(null);
1099
- const displayTitle = title.trim() ? title : placeholder;
1100
- useEffect(() => {
1101
- if (isEditing)
1102
- resizeEditableTextarea(textareaRef.current);
1103
- }, [isEditing, title]);
1104
- function startEditing() {
1105
- if (readOnly)
1106
- return;
1107
- if (!isEditMode)
1108
- onRequestEditMode();
1109
- setIsEditing(true);
1110
- }
1111
- if (readOnly) {
1112
- return (<div className="page-title-edit-target page-title-readonly">
1113
- <h1>{displayTitle}</h1>
1114
- </div>);
1115
- }
1116
- if (isEditing) {
1117
- return (<textarea aria-label={ariaLabel} autoFocus className="page-title-editor viz-card__no-drag" onBlur={() => setIsEditing(false)} onChange={(event) => {
1118
- resizeEditableTextarea(event.currentTarget);
1119
- onChange(event.currentTarget.value);
1120
- }} placeholder={placeholder} ref={textareaRef} rows={1} value={title}/>);
1121
- }
1122
- return (<div aria-label={ariaLabel} className="page-title-edit-target viz-card__no-drag" data-page-title-edit-mode={isEditMode ? "true" : "false"} onClick={() => {
1123
- if (isEditMode)
1124
- startEditing();
1125
- }} onDoubleClick={startEditing} onKeyDown={(event) => {
1126
- if (event.key === "Enter" || event.key === " ") {
1127
- event.preventDefault();
1128
- startEditing();
1129
- }
1130
- }} role="button" tabIndex={0}>
1131
- <h1>{displayTitle}</h1>
1132
- </div>);
1133
- }
1134
- function composeHeaderMarkdown(title, description) {
1135
- return description?.trim() ? `## ${title}\n\n${description}` : `## ${title}`;
1136
- }
1137
- function composeVisualHeaderMarkdown(title, description, headerMarkdown) {
1138
- if (headerMarkdown?.trim()) {
1139
- return headerMarkdown;
1140
- }
1141
- return composeHeaderMarkdown(title, description);
1142
- }
1143
- function composePageTitle(manifest) {
1144
- const fallbackTitle = manifest?.surface === "report" ? "Data Analytics Report" : "Data Analytics Dashboard";
1145
- return manifest?.title?.trim() || fallbackTitle;
1146
- }
1147
- function composeChartHeaderMarkdown(chart) {
1148
- return composeVisualHeaderMarkdown(chart.title, chart.showDescription ? chart.subtitle : undefined, chart.headerMarkdown);
1149
- }
1150
- function composeTableHeaderMarkdown(table) {
1151
- return composeVisualHeaderMarkdown(table.title, table.showDescription ? table.subtitle : undefined, table.headerMarkdown);
1152
- }
1153
- function reportBlockBodyMarkdown(block) {
1154
- return typeof block.body === "string" ? block.body : "";
1155
- }
1156
- function visibleString(value) {
1157
- return typeof value === "string" && value.trim() ? value : undefined;
1158
- }
1159
- function composeBlockMarkdown(block, textOverride) {
1160
- if (visibleString(textOverride?.bodyMarkdown))
1161
- return textOverride.bodyMarkdown;
1162
- return reportBlockBodyMarkdown(block);
1163
- }
1164
- function composeBlockHtml(block, textOverride) {
1165
- if (visibleString(textOverride?.html))
1166
- return textOverride.html;
1167
- return typeof block.body === "string" ? block.body : "";
1168
- }
1169
- const REPORT_HTML_BLOCK_CSP = [
1170
- "default-src 'none'",
1171
- "base-uri 'none'",
1172
- "connect-src 'none'",
1173
- "font-src data:",
1174
- "form-action 'none'",
1175
- "frame-src 'none'",
1176
- "img-src data: blob:",
1177
- "media-src data: blob:",
1178
- "object-src 'none'",
1179
- "script-src 'none'",
1180
- "style-src 'unsafe-inline'",
1181
- ].join("; ");
1182
- function sandboxedReportHtml(html) {
1183
- return `<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="${REPORT_HTML_BLOCK_CSP}"><meta name="viewport" content="width=device-width, initial-scale=1"><base target="_blank"><style>html,body{margin:0;background:transparent;}img,svg,canvas,video{max-width:100%;height:auto;}</style></head><body>${html}</body></html>`;
1184
- }
1185
- function measureHtmlFrameHeight(frame) {
1186
- const documentElement = frame?.contentDocument?.documentElement;
1187
- const body = frame?.contentDocument?.body;
1188
- if (!documentElement && !body)
1189
- return 0;
1190
- return Math.ceil(Math.max(documentElement?.scrollHeight ?? 0, body?.scrollHeight ?? 0));
1191
- }
1192
- function markdownPlainText(markdown) {
1193
- return markdown
1194
- .replace(/^#{1,6}\s+/gm, "")
1195
- .replace(/\*\*([^*]+)\*\*/g, "$1")
1196
- .replace(/`([^`]+)`/g, "$1")
1197
- .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
1198
- .trim();
1199
- }
1200
- function markdownFirstLine(markdown, fallback) {
1201
- const first = markdownPlainText(markdown).split(/\r?\n/).find((line) => line.trim());
1202
- return first?.trim() || fallback;
1203
- }
1204
- function ChartBody({ accessIssue, chart, filters, isFullscreen = false, selectedFilters, snapshot }) {
1205
- const [visibleSeries, setVisibleSeries] = useState();
1206
- const rawRows = filterRowsForDataset(getRows(snapshot, chart.dataset), chart.dataset, filters, selectedFilters, chartUsedFields(chart));
1207
- if (accessIssue) {
1208
- return (<div className="permission-card">
1209
- <div className="permission-card-title">Missing data access</div>
1210
- <p>{accessIssue.message}</p>
1211
- {accessIssue.actionHref ? (<a href={accessIssue.actionHref} rel="noreferrer" target="_blank">
1212
- {accessIssue.actionLabel ?? "Request access"}
1213
- </a>) : accessIssue.actionLabel ? (<span>{accessIssue.actionLabel}</span>) : null}
1214
- </div>);
1215
- }
1216
- if (!rawRows.length) {
1217
- return <div className="empty-state">No rows match the selected filters.</div>;
1218
- }
1219
- return (<ChartRenderer chart={chart} height={isFullscreen ? CHART_FULLSCREEN_HEIGHT : undefined} onVisibleSeriesChange={setVisibleSeries} rows={rawRows} surface={isFullscreen ? "explorer" : "card"} visibleSeries={visibleSeries}/>);
1220
- }
1221
- function VizCard({ accessIssue, chart, children, isEditMode, isMenuOpen, layout, onCopyResult, onDeleteBlock, onRequestEditMode, onTextChange, onMenuOpenChange, onModalOpen, textOverride }) {
1222
- const cardRef = useRef(null);
1223
- const { closeMenu, fixedMenuStyle, handleMenuButtonKeyDown, handleMenuKeyDown, menuButtonRef, menuMotionClass, menuRef, toggleMenu, shouldRenderMenu } = useDashboardMenu(isMenuOpen, onMenuOpenChange);
1224
- const [imageExportState, setImageExportState] = useState({ status: "idle" });
1225
- const { getPreparedImageBlob, preparedImageExportStatus, prepareImageExport, resetPreparedImageExport } = usePreparedImageExport(cardRef);
1226
- const fallbackHeaderMarkdown = textOverride?.title || textOverride?.subtitle
1227
- ? composeHeaderMarkdown(textOverride.title ?? chart.title, textOverride.subtitle ?? chart.subtitle)
1228
- : composeChartHeaderMarkdown(chart);
1229
- const displayHeaderMarkdown = textOverride?.headerMarkdown ?? fallbackHeaderMarkdown;
1230
- const displayChart = {
1231
- ...chart,
1232
- subtitle: undefined,
1233
- title: markdownFirstLine(displayHeaderMarkdown, chart.title)
1234
- };
1235
- function prepareImageExportQuietly(force = false) {
1236
- if (accessIssue || !shouldOfferImageClipboardCopy())
1237
- return;
1238
- const prepared = prepareImageExport({ force });
1239
- if (prepared)
1240
- void prepared.promise.catch(() => undefined);
1241
- }
1242
- async function handleCopyAsImage() {
1243
- if (!cardRef.current)
1244
- return;
1245
- setImageExportState({ status: "loading" });
1246
- try {
1247
- const copyResult = await copyElementAsImage(cardRef.current, getPreparedImageBlob());
1248
- setImageExportState({ status: "idle" });
1249
- resetPreparedImageExport();
1250
- onCopyResult(imageCopySuccessMessage("Copied widget as image.", copyResult));
1251
- }
1252
- catch (error) {
1253
- setImageExportState({
1254
- error: error instanceof Error ? error.message : "Failed to copy image.",
1255
- status: "error"
1256
- });
1257
- onCopyResult(error instanceof Error ? error.message : "Failed to copy image.", true);
1258
- }
1259
- }
1260
- const menuItem = (label, icon, onClick, disabled = false, tone = "default", onPrepare) => (<button className={`viz-card-menu-item ${tone === "danger" ? "viz-card-menu-item-danger" : ""}`.trim()} disabled={disabled} key={label} onFocus={onPrepare} onClick={() => {
1261
- void onClick();
1262
- closeMenu();
1263
- }} onPointerEnter={onPrepare} role="menuitem" type="button">
1264
- <span aria-hidden="true" className="viz-card-menu-icon">
1265
- {icon}
1266
- </span>
1267
- <span>{label}</span>
1268
- </button>);
1269
- return (<section className={`panel chart-panel viz-card ${accessIssue ? "has-permission-issue" : ""}`} id={chart.id} ref={cardRef}>
1270
- <PanelHeader action={<div className="viz-card-actions" data-image-export-exclude="true" ref={menuRef}>
1271
- <button aria-expanded={isMenuOpen} aria-label={`Open options for ${displayChart.title}`} className="viz-card-menu-button viz-card__no-drag" onClick={(event) => {
1272
- event.stopPropagation();
1273
- const nextIsMenuOpen = toggleMenu();
1274
- if (nextIsMenuOpen) {
1275
- prepareImageExportQuietly(true);
1276
- }
1277
- else {
1278
- resetPreparedImageExport();
1279
- }
1280
- }} onFocus={() => prepareImageExportQuietly()} onKeyDown={handleMenuButtonKeyDown} onPointerEnter={() => prepareImageExportQuietly()} ref={menuButtonRef} type="button">
1281
- <Ellipsis aria-hidden="true" size={18} strokeWidth={2}/>
1282
- </button>
1283
- {shouldRenderMenu ? (<div className={`viz-card-menu viz-card__no-drag menu-surface ${menuMotionClass}`} onKeyDown={handleMenuKeyDown} role="menu" style={fixedMenuStyle}>
1284
- {menuItem("Edit chart", <ChartNoAxesCombined size={18} strokeWidth={2}/>, () => onModalOpen({ chart: displayChart, kind: "fullscreen" }))}
1285
- {menuItem("View data source", <Database size={18} strokeWidth={2}/>, () => onModalOpen({ chart: displayChart, kind: "source" }))}
1286
- {shouldOfferImageClipboardCopy()
1287
- ? menuItem("Copy as image", <Camera size={18} strokeWidth={2}/>, handleCopyAsImage, Boolean(accessIssue) ||
1288
- imageExportState.status === "loading" ||
1289
- preparedImageExportStatus === "pending", "default", prepareImageExportQuietly)
1290
- : null}
1291
- {onDeleteBlock ? menuItem("Delete", <Trash2 size={18} strokeWidth={2}/>, onDeleteBlock, false, "danger") : null}
1292
- </div>) : null}
1293
- </div>} subtitle={displayChart.subtitle} title={displayChart.title} titleRowClassName="viz-card__drag-handle">
1294
- <RichMarkdown ariaLabel={`Edit markdown header for ${chart.title}`} className="editable-cell-header" isEditMode={isEditMode} markdown={displayHeaderMarkdown} onMarkdownChange={(nextMarkdown) => onTextChange(chart.id, { headerMarkdown: nextMarkdown })} onRequestEditMode={onRequestEditMode} placeholder={composeChartHeaderMarkdown(chart)} variant="cellHeader"/>
1295
- </PanelHeader>
1296
- {children}
1297
- </section>);
1298
- }
1299
- function AccessIssueStrip({ issues }) {
1300
- if (!issues.length)
1301
- return null;
1302
- return (<section className="access-issue-strip" aria-label="Data access issues">
1303
- <div>
1304
- <strong>{issues.length === 1 ? "Data access blocker" : "Data access blockers"}</strong>
1305
- <p>Some report data could not load because the source query could not complete.</p>
1306
- </div>
1307
- <ul>
1308
- {issues.map((issue) => (<li key={issue.id}>
1309
- <span>{issue.scope ?? issue.dataset ?? issue.sourceId ?? issue.id}</span>
1310
- <span>{issue.message}</span>
1311
- {issue.actionHref ? (<a href={issue.actionHref} rel="noreferrer" target="_blank">
1312
- {issue.actionLabel ?? "Request access"}
1313
- </a>) : null}
1314
- </li>))}
1315
- </ul>
1316
- </section>);
1317
- }
1318
- const SQL_KEYWORDS = new Set([
1319
- "and",
1320
- "as",
1321
- "asc",
1322
- "by",
1323
- "case",
1324
- "desc",
1325
- "distinct",
1326
- "else",
1327
- "end",
1328
- "from",
1329
- "group",
1330
- "in",
1331
- "is",
1332
- "join",
1333
- "left",
1334
- "like",
1335
- "max",
1336
- "min",
1337
- "not",
1338
- "null",
1339
- "on",
1340
- "or",
1341
- "order",
1342
- "over",
1343
- "partition",
1344
- "right",
1345
- "select",
1346
- "sum",
1347
- "then",
1348
- "when",
1349
- "where",
1350
- "with"
1351
- ]);
1352
- const SQL_FUNCTIONS = new Set([
1353
- "avg",
1354
- "cast",
1355
- "coalesce",
1356
- "concat",
1357
- "count",
1358
- "current_date",
1359
- "date_trunc",
1360
- "dateadd",
1361
- "date_add",
1362
- "round",
1363
- "nullif"
1364
- ]);
1365
- const SQL_TOKEN_PATTERN = /(--[^\n]*|'(?:''|[^'])*'|<>|!=|<=|>=|\b\d+(?:\.\d+)?\b|\b[a-zA-Z_][a-zA-Z0-9_]*\b|[(),.;=*+\-/%<>])/g;
1366
- const SQL_FORMAT_LINE_STARTERS = new Set([
1367
- "from",
1368
- "group",
1369
- "having",
1370
- "limit",
1371
- "order",
1372
- "select",
1373
- "union",
1374
- "where",
1375
- "with"
1376
- ]);
1377
- const SQL_JOIN_MODIFIERS = new Set([
1378
- "cross",
1379
- "full",
1380
- "inner",
1381
- "join",
1382
- "left",
1383
- "outer",
1384
- "right"
1385
- ]);
1386
- function sqlFormatTokens(sql) {
1387
- const tokens = [];
1388
- let cursor = 0;
1389
- for (const match of sql.matchAll(SQL_TOKEN_PATTERN)) {
1390
- const token = match[0];
1391
- const index = match.index ?? 0;
1392
- const rawGap = sql.slice(cursor, index).trim();
1393
- if (rawGap)
1394
- tokens.push(...rawGap.split(/\s+/));
1395
- tokens.push(token);
1396
- cursor = index + token.length;
1397
- }
1398
- const tail = sql.slice(cursor).trim();
1399
- if (tail)
1400
- tokens.push(...tail.split(/\s+/));
1401
- return tokens;
1402
- }
1403
- function isSqlWord(token) {
1404
- return /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(token);
1405
- }
1406
- function formatSqlForDisplay(sql) {
1407
- const tokens = sqlFormatTokens(sql.trim());
1408
- if (!tokens.length)
1409
- return "";
1410
- const lines = [];
1411
- let current = "";
1412
- let indent = 0;
1413
- const contextStack = [];
1414
- let previousToken = "";
1415
- function currentIndent(level = indent) {
1416
- return " ".repeat(Math.max(0, level));
1417
- }
1418
- function pushLine(nextIndent = indent) {
1419
- const text = current.trimEnd();
1420
- if (text.trim())
1421
- lines.push(text);
1422
- current = currentIndent(nextIndent);
1423
- }
1424
- function append(token, { tight = false } = {}) {
1425
- if (!current)
1426
- current = currentIndent();
1427
- const trimmed = current.trimEnd();
1428
- const needsSpace = !tight &&
1429
- trimmed &&
1430
- !trimmed.endsWith("(") &&
1431
- !trimmed.endsWith(".") &&
1432
- token !== "." &&
1433
- token !== "," &&
1434
- token !== ")" &&
1435
- token !== ";";
1436
- current = `${trimmed}${needsSpace ? " " : ""}${token}`;
1437
- previousToken = token;
1438
- }
1439
- for (let index = 0; index < tokens.length; index += 1) {
1440
- const token = tokens[index];
1441
- const lower = token.toLowerCase();
1442
- const previousLower = previousToken.toLowerCase();
1443
- const nextLower = tokens[index + 1]?.toLowerCase?.() ?? "";
1444
- if (token.startsWith("--")) {
1445
- if (current.trim())
1446
- pushLine();
1447
- append(token);
1448
- pushLine();
1449
- continue;
1450
- }
1451
- if (SQL_FORMAT_LINE_STARTERS.has(lower)) {
1452
- if (current.trim() && !current.trimEnd().endsWith("("))
1453
- pushLine();
1454
- append(lower.toUpperCase());
1455
- continue;
1456
- }
1457
- if (SQL_JOIN_MODIFIERS.has(lower)) {
1458
- if (!(lower === "join" && SQL_JOIN_MODIFIERS.has(previousLower)) && current.trim())
1459
- pushLine();
1460
- append(lower.toUpperCase());
1461
- continue;
1462
- }
1463
- if (token === "(") {
1464
- const functionCall = SQL_FUNCTIONS.has(previousLower) ||
1465
- (isSqlWord(previousToken) && !SQL_KEYWORDS.has(previousLower) && previousLower !== "as");
1466
- append(token, { tight: functionCall });
1467
- contextStack.push(functionCall ? "function" : "group");
1468
- if (!functionCall && (nextLower === "select" || previousLower === "as")) {
1469
- indent += 1;
1470
- pushLine();
1471
- }
1472
- else if (!functionCall) {
1473
- indent += 1;
1474
- }
1475
- continue;
1476
- }
1477
- if (token === ")") {
1478
- const context = contextStack.pop();
1479
- const nextIndent = Math.max(0, indent - 1);
1480
- if (context !== "function" && current.trim() && current.trim() !== currentIndent().trim())
1481
- pushLine(nextIndent);
1482
- indent = nextIndent;
1483
- append(token, { tight: true });
1484
- continue;
1485
- }
1486
- if (token === ",") {
1487
- append(token, { tight: true });
1488
- if (contextStack[contextStack.length - 1] !== "function")
1489
- pushLine();
1490
- continue;
1491
- }
1492
- if (token === ".") {
1493
- append(token, { tight: true });
1494
- continue;
1495
- }
1496
- if (token === ";") {
1497
- append(token, { tight: true });
1498
- pushLine();
1499
- continue;
1500
- }
1501
- append(SQL_KEYWORDS.has(lower) || SQL_FUNCTIONS.has(lower) ? lower.toUpperCase() : token);
1502
- }
1503
- if (current.trim())
1504
- pushLine();
1505
- return lines.join("\n");
1506
- }
1507
- function highlightSql(sql) {
1508
- const nodes = [];
1509
- let cursor = 0;
1510
- for (const match of sql.matchAll(SQL_TOKEN_PATTERN)) {
1511
- const token = match[0];
1512
- const index = match.index ?? 0;
1513
- if (index > cursor) {
1514
- nodes.push(sql.slice(cursor, index));
1515
- }
1516
- const lower = token.toLowerCase();
1517
- let className = "sql-token";
1518
- if (token.startsWith("--")) {
1519
- className += " comment";
1520
- }
1521
- else if (token.startsWith("'")) {
1522
- className += " string";
1523
- }
1524
- else if (/^\d/.test(token)) {
1525
- className += " number";
1526
- }
1527
- else if (SQL_KEYWORDS.has(lower)) {
1528
- className += " keyword";
1529
- }
1530
- else if (SQL_FUNCTIONS.has(lower)) {
1531
- className += " function";
1532
- }
1533
- else if (/^[(),.;=*+\-/%]$/.test(token)) {
1534
- className += " punctuation";
1535
- }
1536
- else {
1537
- className += " identifier";
1538
- }
1539
- nodes.push(<span className={className} key={`${index}-${token}`}>
1540
- {token}
1541
- </span>);
1542
- cursor = index + token.length;
1543
- }
1544
- if (cursor < sql.length) {
1545
- nodes.push(sql.slice(cursor));
1546
- }
1547
- return nodes;
1548
- }
1549
- const SOURCE_FETCH_TIMEOUT_MS = 10000;
1550
- function DataSourceDetails({ children, details, source, sourceQuery }) {
1551
- return (<div className="source-modal-sections">
1552
- <section className="source-modal-section">
1553
- <h3>Details</h3>
1554
- <dl className="details-grid source-details-grid">
1555
- <div>
1556
- <dt>Dataset</dt>
1557
- <dd>{details.dataset}</dd>
1558
- </div>
1559
- <div>
1560
- <dt>Tables used</dt>
1561
- <dd>{detailList(details.tables)}</dd>
1562
- </div>
1563
- <div>
1564
- <dt>Filters</dt>
1565
- <dd>{detailText(details.filters)}</dd>
1566
- </div>
1567
- <div>
1568
- <dt>Metric definitions</dt>
1569
- <dd>{detailList(details.metricDefinitions)}</dd>
1570
- </div>
1571
- <div>
1572
- <dt>Snapshot</dt>
1573
- <dd>{formatDate(details.snapshot)}</dd>
1574
- </div>
1575
- </dl>
1576
- </section>
1577
- <section className="source-modal-section">
1578
- <h3>Source query</h3>
1579
- <SourceQueryBlock source={source} sourceQuery={sourceQuery}/>
1580
- </section>
1581
- <section className="source-modal-section">
1582
- <h3>Data table</h3>
1583
- {children}
1584
- </section>
1585
- </div>);
1586
- }
1587
- function SourceQueryBlock({ source, sourceQuery }) {
1588
- const [sourceContent, setSourceContent] = useState({ status: "idle" });
1589
- const [copyStatus, setCopyStatus] = useState("idle");
1590
- const codeRef = useRef(null);
1591
- const inlineSourceText = queryTextFromSourceQuery(sourceQueryFromSourceSpec(source)) || queryTextFromSourceQuery(sourceQuery) || "";
1592
- const displaySourceText = sourceContent.status === "loaded" ? formatSqlForDisplay(sourceContent.text) : "";
1593
- useEffect(() => {
1594
- if (inlineSourceText) {
1595
- setSourceContent({ status: "loaded", text: inlineSourceText });
1596
- return;
1597
- }
1598
- if (!source?.path) {
1599
- setSourceContent({ status: "idle" });
1600
- return;
1601
- }
1602
- let cancelled = false;
1603
- const controller = new AbortController();
1604
- const timeout = window.setTimeout(() => controller.abort(), SOURCE_FETCH_TIMEOUT_MS);
1605
- setSourceContent({ status: "loading" });
1606
- fetch(`/api/source-file?path=${encodeURIComponent(source.path)}`, {
1607
- cache: "no-store",
1608
- signal: controller.signal
1609
- })
1610
- .then(async (response) => {
1611
- const text = await response.text();
1612
- if (!response.ok)
1613
- throw new Error(text || `Request failed: ${response.status}`);
1614
- return text;
1615
- })
1616
- .then((text) => {
1617
- if (!cancelled)
1618
- setSourceContent({ status: "loaded", text });
1619
- })
1620
- .catch((error) => {
1621
- if (!cancelled) {
1622
- const isAbort = error instanceof Error && error.name === "AbortError";
1623
- setSourceContent({
1624
- error: isAbort
1625
- ? "Source request timed out. Refresh the app and try again."
1626
- : error instanceof Error
1627
- ? error.message
1628
- : "Failed to load source",
1629
- status: "error"
1630
- });
1631
- }
1632
- })
1633
- .finally(() => {
1634
- window.clearTimeout(timeout);
1635
- });
1636
- return () => {
1637
- cancelled = true;
1638
- window.clearTimeout(timeout);
1639
- controller.abort();
1640
- };
1641
- }, [inlineSourceText, source?.path]);
1642
- useEffect(() => {
1643
- if (copyStatus === "idle")
1644
- return;
1645
- const timeout = window.setTimeout(() => setCopyStatus("idle"), 1800);
1646
- return () => window.clearTimeout(timeout);
1647
- }, [copyStatus]);
1648
- async function handleCopyQuery(text) {
1649
- try {
1650
- await copyTextToClipboard(text);
1651
- setCopyStatus("copied");
1652
- }
1653
- catch {
1654
- setCopyStatus("blocked");
1655
- }
1656
- }
1657
- if (sourceContent.status === "loading")
1658
- return <>Loading source...</>;
1659
- if (sourceContent.status === "error") {
1660
- return <span className="source-error">{sourceContent.error}</span>;
1661
- }
1662
- if (sourceContent.status === "loaded") {
1663
- return (<div className="source-query-shell">
1664
- {source?.path || source?.href || source?.label || sourceQuery?.id || sourceQuery?.engine ? (<div className="source-query-meta">
1665
- <span>
1666
- {source?.href ? (<a href={source.href} rel="noreferrer" target="_blank">
1667
- {source.path ?? source.label}
1668
- </a>) : (source?.path ?? source?.label ?? sourceQuery?.id ?? sourceQuery?.engine)}
1669
- </span>
1670
- <button className="source-query-copy" onClick={() => void handleCopyQuery(displaySourceText || sourceContent.text)} type="button">
1671
- <Copy aria-hidden="true" size={14} strokeWidth={2}/>
1672
- {copyStatus === "copied"
1673
- ? "Copied"
1674
- : copyStatus === "blocked"
1675
- ? "Copy failed"
1676
- : "Copy query"}
1677
- </button>
1678
- </div>) : null}
1679
- <pre className="source-query">
1680
- <code ref={codeRef}>{highlightSql(displaySourceText || sourceContent.text)}</code>
1681
- </pre>
1682
- </div>);
1683
- }
1684
- return <>No source query file mapped.</>;
1685
- }
1686
- function useModalScrollLock(enabled) {
1687
- useEffect(() => {
1688
- if (!enabled)
1689
- return undefined;
1690
- const previousOverflow = document.body.style.overflow;
1691
- const previousOverscrollBehavior = document.body.style.overscrollBehavior;
1692
- document.body.style.overflow = "hidden";
1693
- document.body.style.overscrollBehavior = "none";
1694
- return () => {
1695
- document.body.style.overflow = previousOverflow;
1696
- document.body.style.overscrollBehavior = previousOverscrollBehavior;
1697
- };
1698
- }, [enabled]);
1699
- }
1700
- function sourcePreviewColumns(rows, columns = []) {
1701
- if (columns.length)
1702
- return columns;
1703
- const fields = [];
1704
- const seen = new Set();
1705
- for (const row of rows) {
1706
- for (const field of Object.keys(row)) {
1707
- if (!seen.has(field)) {
1708
- seen.add(field);
1709
- fields.push(field);
1710
- }
1711
- }
1712
- }
1713
- return fields.map((field) => ({ field, label: field }));
1714
- }
1715
- function SourceDataTable({ columns = [], dataset, density = "dense", rows = [] }) {
1716
- const previewRows = useMemo(() => asArray(rows).filter((row) => row && typeof row === "object"), [rows]);
1717
- const previewDataset = dataset ?? "__source_preview_rows";
1718
- const table = useMemo(() => ({
1719
- columns: sourcePreviewColumns(previewRows, columns),
1720
- dataset: previewDataset,
1721
- id: `source-preview-${previewDataset}`
1722
- }), [columns, previewDataset, previewRows]);
1723
- const snapshot = useMemo(() => ({ datasets: { [previewDataset]: previewRows } }), [previewDataset, previewRows]);
1724
- const [columnWidths, setColumnWidths] = useState({});
1725
- useEffect(() => {
1726
- setColumnWidths({});
1727
- }, [table.id]);
1728
- return (<div className="source-data-table">
1729
- <TableContent allowColumnResize={false} columnWidths={columnWidths} density={density} filters={EMPTY_FILTERS} onColumnWidthsChange={(_tableId, nextWidths) => setColumnWidths(nextWidths)} selectedFilters={{}} snapshot={snapshot} table={table}/>
1730
- </div>);
1731
- }
1732
- function querySourceForChart(chart, sources) {
1733
- const directSource = sourceForChart(chart, sources);
1734
- return (directSource ??
1735
- sources.find((source) => {
1736
- const label = source.label?.toLowerCase() ?? "";
1737
- const path = source.path?.toLowerCase() ?? "";
1738
- return path.endsWith(".sql") || label.includes("sql") || label.includes("quer");
1739
- }) ??
1740
- null);
1741
- }
1742
- function chartMetricsForBuildDetails(chart) {
1743
- const metrics = [];
1744
- const seen = new Set();
1745
- function addMetric(field, label) {
1746
- if (!field || seen.has(field))
1747
- return;
1748
- seen.add(field);
1749
- metrics.push({ field, label: label || field });
1750
- }
1751
- addMetric(chart.encodings?.y?.field, chart.encodings?.y?.label);
1752
- for (const field of chart.encodings?.y?.fields ?? []) {
1753
- addMetric(field, field);
1754
- }
1755
- return metrics;
1756
- }
1757
- function ChartSourceModalDialog({ activeFilters, chart, manifest, onClose, rows = [], snapshot }) {
1758
- const dialogRef = useRef(null);
1759
- const source = querySourceForChart(chart, manifest?.sources ?? []);
1760
- const sourceQuery = sourceQueryFromSourceSpec(source);
1761
- const buildDetails = sourceBuildDetails({
1762
- activeFilters,
1763
- dataset: chart.dataset,
1764
- metrics: chartMetricsForBuildDetails(chart),
1765
- source,
1766
- sourceQuery,
1767
- snapshot
1768
- });
1769
- useModalScrollLock(true);
1770
- useEffect(() => {
1771
- const dialog = dialogRef.current;
1772
- if (dialog && !dialog.open) {
1773
- dialog.showModal();
1774
- }
1775
- }, []);
1776
- return (<dialog aria-labelledby="chart-source-modal-title" className="native-modal source-modal" onCancel={onClose} onClick={(event) => {
1777
- if (event.target === event.currentTarget) {
1778
- event.currentTarget.close();
1779
- }
1780
- }} onClose={onClose} ref={dialogRef}>
1781
- <section className="modal-panel source-modal-panel">
1782
- <div className="modal-header">
1783
- <div>
1784
- <h2 id="chart-source-modal-title">Data source</h2>
1785
- <p>{chart.title}</p>
1786
- </div>
1787
- <button aria-label="Close data source" className="modal-close-button" onClick={() => dialogRef.current?.close()} type="button">
1788
- <X aria-hidden="true" size={20} strokeWidth={2}/>
1789
- </button>
1790
- </div>
1791
- <DataSourceDetails details={buildDetails} source={source} sourceQuery={sourceQuery}>
1792
- <SourceDataTable dataset={chart.dataset} rows={rows}/>
1793
- </DataSourceDetails>
1794
- </section>
1795
- </dialog>);
1796
- }
1797
- function safeScriptJson(value) {
1798
- return JSON.stringify(value).replace(/</g, "\\u003c");
1799
- }
1800
- function chartWidgetDetailHtml(html, widgetInstanceId) {
1801
- const bridge = `<script>
1802
- window.openai = {
1803
- ...(window.openai || {}),
1804
- availableDisplayModes: ["modal"],
1805
- displayMode: "modal",
1806
- widgetInstanceId: ${safeScriptJson(widgetInstanceId)},
1807
- requestDisplayMode(request) {
1808
- const mode = typeof request === "string" ? request : request && request.mode;
1809
- window.parent.postMessage({ type: "datascience-chart-widget-display-mode", mode }, "*");
1810
- return Promise.resolve({ mode });
1811
- },
1812
- sendFollowUpMessage(payload) {
1813
- window.parent.postMessage(
1814
- {
1815
- originUrl: payload && payload.originUrl,
1816
- prompt: payload && payload.prompt,
1817
- type: "datascience-chart-widget-codex-prompt"
1818
- },
1819
- "*"
1820
- );
1821
- return Promise.resolve({ ok: true });
1822
- },
1823
- openCodexPrompt(payload) {
1824
- return this.sendFollowUpMessage(payload);
1825
- }
1826
- };
1827
- </script>`;
1828
- return html.includes("</head>") ? html.replace("</head>", `${bridge}</head>`) : `${bridge}${html}`;
1829
- }
1830
- function shouldUseHostedChartModal(packageInfo) {
1831
- return packageInfo?.hostedReadOnly === true || packageInfo?.deliveryMode === "site_creator";
1832
- }
1833
- function ChartDetailPage({ accessIssue, chart, filters, manifest, onChartSpecChange, onClose, packageInfo, rows, selectedFilters, snapshot }) {
1834
- const dialogRef = useRef(null);
1835
- const iframeRef = useRef(null);
1836
- const pendingPostTimersRef = useRef([]);
1837
- const [widgetHtml, setWidgetHtml] = useState(null);
1838
- const [widgetError, setWidgetError] = useState(null);
1839
- const [sourceQueryText, setSourceQueryText] = useState(null);
1840
- const source = querySourceForChart(chart, manifest?.sources ?? []);
1841
- const hostedChartModal = shouldUseHostedChartModal(packageInfo);
1842
- const widgetInstanceId = `report-chart-detail-${chart.id}`;
1843
- const widgetPayload = useMemo(() => chartWidgetPayload(chart, rows, source, snapshot, sourceQueryText), [chart, rows, source, snapshot, sourceQueryText]);
1844
- const widgetUrl = useMemo(() => `/api/inline-chart-widget?displayMode=modal&widgetInstanceId=${encodeURIComponent(widgetInstanceId)}`, [widgetInstanceId]);
1845
- const clearPendingPostTimers = useCallback(() => {
1846
- pendingPostTimersRef.current.forEach((timer) => window.clearTimeout(timer));
1847
- pendingPostTimersRef.current = [];
1848
- }, []);
1849
- const postWidgetPayload = useCallback(() => {
1850
- iframeRef.current?.contentWindow?.postMessage({
1851
- displayMode: "modal",
1852
- payload: widgetPayload,
1853
- targetWidgetInstanceId: widgetInstanceId
1854
- }, "*");
1855
- }, [widgetInstanceId, widgetPayload]);
1856
- const scheduleWidgetPayloadPosts = useCallback(() => {
1857
- clearPendingPostTimers();
1858
- pendingPostTimersRef.current = [0, 50, 150, 350].map((delay) => window.setTimeout(postWidgetPayload, delay));
1859
- }, [clearPendingPostTimers, postWidgetPayload]);
1860
- useEffect(() => {
1861
- const dialog = dialogRef.current;
1862
- if (dialog && !dialog.open) {
1863
- dialog.showModal();
1864
- }
1865
- }, []);
1866
- useEffect(() => {
1867
- let cancelled = false;
1868
- if (hostedChartModal) {
1869
- setWidgetHtml(null);
1870
- setWidgetError(null);
1871
- return () => {
1872
- cancelled = true;
1873
- };
1874
- }
1875
- setWidgetHtml(null);
1876
- setWidgetError(null);
1877
- void fetch(widgetUrl)
1878
- .then((response) => {
1879
- if (!response.ok)
1880
- throw new Error(`Shared chart detail failed to load (${response.status}).`);
1881
- return response.text();
1882
- })
1883
- .then((html) => {
1884
- if (!cancelled)
1885
- setWidgetHtml(chartWidgetDetailHtml(html, widgetInstanceId));
1886
- })
1887
- .catch((error) => {
1888
- if (!cancelled)
1889
- setWidgetError(error instanceof Error ? error.message : "Shared chart detail failed to load.");
1890
- });
1891
- return () => {
1892
- cancelled = true;
1893
- };
1894
- }, [hostedChartModal, widgetInstanceId, widgetUrl]);
1895
- useEffect(() => {
1896
- let cancelled = false;
1897
- if (hostedChartModal) {
1898
- setSourceQueryText(null);
1899
- return () => {
1900
- cancelled = true;
1901
- };
1902
- }
1903
- const inlineSourceText = queryTextFromSourceQuery(sourceQueryFromSourceSpec(source));
1904
- if (inlineSourceText) {
1905
- setSourceQueryText(inlineSourceText);
1906
- return () => {
1907
- cancelled = true;
1908
- };
1909
- }
1910
- if (!source?.path) {
1911
- setSourceQueryText(null);
1912
- return () => {
1913
- cancelled = true;
1914
- };
1915
- }
1916
- setSourceQueryText(null);
1917
- void fetch(`/api/source-file?path=${encodeURIComponent(source.path)}`, {
1918
- headers: { Accept: "text/plain" }
1919
- })
1920
- .then((response) => {
1921
- if (!response.ok)
1922
- return "";
1923
- return response.text();
1924
- })
1925
- .then((text) => {
1926
- if (!cancelled)
1927
- setSourceQueryText(text.trim() || null);
1928
- })
1929
- .catch(() => {
1930
- if (!cancelled)
1931
- setSourceQueryText(null);
1932
- });
1933
- return () => {
1934
- cancelled = true;
1935
- };
1936
- }, [hostedChartModal, source?.path, source?.query?.query]);
1937
- useEffect(() => {
1938
- if (hostedChartModal || !widgetHtml)
1939
- return;
1940
- scheduleWidgetPayloadPosts();
1941
- }, [hostedChartModal, scheduleWidgetPayloadPosts, widgetHtml]);
1942
- useEffect(() => clearPendingPostTimers, [clearPendingPostTimers]);
1943
- useEffect(() => {
1944
- if (hostedChartModal)
1945
- return undefined;
1946
- function handleWidgetMessage(event) {
1947
- const data = event.data;
1948
- if (!data || typeof data !== "object")
1949
- return;
1950
- if (data.type === "datascience-chart-widget-display-mode" && data.mode === "inline") {
1951
- onClose();
1952
- }
1953
- if (data.type === "datascience-chart-widget-spec-reset" && data.widgetInstanceId === widgetInstanceId) {
1954
- onChartSpecChange(chart.id, null);
1955
- }
1956
- if (data.type === "datascience-chart-widget-spec-change" && data.widgetInstanceId === widgetInstanceId) {
1957
- onChartSpecChange(chart.id, data.visualization_spec);
1958
- }
1959
- if (data.type === "datascience-chart-widget-codex-prompt" && typeof data.prompt === "string") {
1960
- sendCodexPromptToHost(data.prompt, null);
1961
- }
1962
- }
1963
- window.addEventListener("message", handleWidgetMessage);
1964
- return () => window.removeEventListener("message", handleWidgetMessage);
1965
- }, [chart.id, hostedChartModal, onChartSpecChange, onClose, widgetInstanceId]);
1966
- return (<dialog aria-label={`Edit ${chart.title}`} className={`native-modal chart-explore-modal ${hostedChartModal ? "chart-hosted-explore-modal" : ""}`.trim()} onCancel={onClose} onClick={(event) => {
1967
- if (event.target === event.currentTarget) {
1968
- event.currentTarget.close();
1969
- }
1970
- }} onClose={onClose} ref={dialogRef}>
1971
- <section className={`modal-panel chart-explore-panel ${hostedChartModal ? "chart-hosted-explore-panel" : ""}`.trim()}>
1972
- <section aria-label={`Edit ${chart.title}`} className={`chart-detail-page unified-chart-detail-page chart-explore-body ${hostedChartModal ? "chart-hosted-explore-body" : ""}`.trim()}>
1973
- {hostedChartModal ? (<ChartBody accessIssue={accessIssue} chart={chart} filters={filters} isFullscreen selectedFilters={selectedFilters} snapshot={snapshot}/>) : null}
1974
- {!hostedChartModal && !widgetHtml && !widgetError ? <div className="chart-detail-loading">Loading chart detail...</div> : null}
1975
- {widgetError ? <div className="empty-state error-state">{widgetError}</div> : null}
1976
- {!hostedChartModal ? (<iframe className="unified-chart-detail-frame" hidden={!widgetHtml || Boolean(widgetError)} onLoad={scheduleWidgetPayloadPosts} ref={iframeRef} srcDoc={widgetHtml ?? ""} title={`Edit ${chart.title}`}/>) : null}
1977
- </section>
1978
- </section>
1979
- </dialog>);
1980
- }
1981
- function chartWidgetColumnType(column, value) {
1982
- if (column?.type === "date")
1983
- return "date";
1984
- if (column?.format || column?.type === "currency" || column?.type === "number" || column?.type === "percent")
1985
- return "number";
1986
- if (typeof value === "number")
1987
- return "number";
1988
- if (typeof value === "string" && /^\d{4}-\d{2}(?:-\d{2})?(?:$|[T\s])/.test(value))
1989
- return "date";
1990
- return "text";
1991
- }
1992
- function chartWidgetEncodingColumn(chart, role, rows) {
1993
- const field = chartEncodingField(chart, role);
1994
- if (!field)
1995
- return null;
1996
- const encoding = chartEncoding(chart, role);
1997
- return {
1998
- key: field,
1999
- label: chartEncodingLabel(chart, role, field),
2000
- type: encoding.type === "temporal" ? "date" : encoding.type === "quantitative" ? "number" : chartWidgetColumnType(encoding, rows[0]?.[field]),
2001
- unit: encoding.unit
2002
- };
2003
- }
2004
- function chartWidgetSource(source, sourceQuery, queryText, snapshot) {
2005
- return {
2006
- id: source?.id,
2007
- label: source?.label,
2008
- path: source?.path,
2009
- href: source?.href,
2010
- query: {
2011
- engine: sourceQuery?.engine ?? source?.label ?? "report manifest",
2012
- executed_at: sourceQuery?.executed_at ?? snapshot?.generatedAt,
2013
- id: sourceQuery?.id ?? source?.path ?? source?.href,
2014
- url: sourceQuery?.url,
2015
- sql: queryText || "",
2016
- description: sourceQuery?.description,
2017
- language: sourceQuery?.language ?? (source?.path?.toLowerCase().endsWith(".sql") ? "SQL" : undefined),
2018
- tables_used: sourceQuery?.tables_used,
2019
- filters: sourceQuery?.filters,
2020
- metric_definitions: sourceQuery?.metric_definitions
2021
- }
2022
- };
2023
- }
2024
- function chartWidgetPayloadFromEncodings(chart, rows, source, snapshot, sourceQueryText) {
2025
- const xField = chartEncodingField(chart, "x");
2026
- const yField = chartEncodingField(chart, "y");
2027
- const yFields = chartEncodingFields(chart, "y");
2028
- const colorField = chartEncodingField(chart, "color");
2029
- const chartSourceQuery = sourceQueryFromChartSpec(chart);
2030
- const sourceSpecQuery = sourceQueryFromSourceSpec(source);
2031
- const sourceQuery = chartSourceQuery ?? sourceSpecQuery;
2032
- const queryText = queryTextFromSourceQuery(chartSourceQuery) ||
2033
- queryTextFromSourceQuery(sourceSpecQuery) ||
2034
- sourceQueryText?.trim();
2035
- const unit = chart.unit ?? chartEncoding(chart, "y").unit ?? (chart.valueFormat === "currency" ? "USD" : chart.valueFormat === "percent" ? "%" : undefined);
2036
- const settings = chartWidgetSettings(chart);
2037
- if (xField && yField) {
2038
- const columns = [
2039
- chartWidgetEncodingColumn(chart, "x", rows),
2040
- colorField ? chartWidgetEncodingColumn(chart, "color", rows) : null,
2041
- chartWidgetEncodingColumn(chart, "y", rows)
2042
- ].filter(Boolean);
2043
- return {
2044
- ok: true,
2045
- widget_type: "chart",
2046
- title: chart.title,
2047
- subtitle: chart.showDescription ? chart.subtitle : undefined,
2048
- source: chartWidgetSource(source, sourceQuery, queryText, snapshot),
2049
- result_table: {
2050
- columns,
2051
- row_count: rows.length,
2052
- rows: rows.map((row) => Object.fromEntries(columns.map((column) => [column.key, row[column.key]]))),
2053
- truncated: false
2054
- },
2055
- visualization_spec: {
2056
- version: "1",
2057
- intent: chart.intent ?? "custom",
2058
- visualization_type: chart.type,
2059
- encodings: {
2060
- x: { field: xField, type: chartEncoding(chart, "x").type ?? "nominal" },
2061
- y: { aggregate: chartEncoding(chart, "y").aggregate ?? "sum", field: yField, type: "quantitative", unit },
2062
- ...(colorField ? { color: { field: colorField, type: chartEncoding(chart, "color").type ?? "nominal" } } : {})
2063
- },
2064
- presentation: {
2065
- show_controls: true,
2066
- unit,
2067
- view_mode: "both"
2068
- },
2069
- settings
2070
- }
2071
- };
2072
- }
2073
- if (xField && yFields.length) {
2074
- const longRows = rows.flatMap((row) => yFields.map((field) => ({
2075
- [xField]: row[xField],
2076
- series: field,
2077
- value: row[field]
2078
- })));
2079
- return {
2080
- ok: true,
2081
- widget_type: "chart",
2082
- title: chart.title,
2083
- subtitle: chart.showDescription ? chart.subtitle : undefined,
2084
- source: chartWidgetSource(source, sourceQuery, queryText, snapshot),
2085
- result_table: {
2086
- columns: [
2087
- { key: xField, label: chartEncodingLabel(chart, "x", xField), type: chartWidgetColumnType(chartEncoding(chart, "x"), rows[0]?.[xField]) },
2088
- { key: "series", label: "Series", type: "text" },
2089
- { key: "value", label: chartEncodingLabel(chart, "y", "Value"), type: "number", unit }
2090
- ],
2091
- row_count: longRows.length,
2092
- rows: longRows,
2093
- truncated: false
2094
- },
2095
- visualization_spec: {
2096
- version: "1",
2097
- intent: chart.intent ?? "custom",
2098
- visualization_type: chart.type,
2099
- encodings: {
2100
- x: { field: xField, type: chartEncoding(chart, "x").type ?? "nominal" },
2101
- y: { aggregate: "sum", field: "value", type: "quantitative", unit },
2102
- color: { field: "series", type: "nominal" }
2103
- },
2104
- presentation: {
2105
- show_controls: true,
2106
- unit,
2107
- view_mode: "both"
2108
- },
2109
- settings
2110
- }
2111
- };
2112
- }
2113
- return null;
2114
- }
2115
- function chartWidgetSettings(chart) {
2116
- const source = chart?.settings && typeof chart.settings === "object" && !Array.isArray(chart.settings) ? chart.settings : {};
2117
- const type = chart?.type;
2118
- const orientation = source.orientation === "horizontal" || type === "horizontalBar" || type === "horizontalStackedBar" || type === "horizontalStackedBar100"
2119
- ? "horizontal"
2120
- : source.orientation === "vertical"
2121
- ? "vertical"
2122
- : undefined;
2123
- const groupMode = source.groupMode ?? source.group_mode ?? (type === "stackedBar100" || type === "horizontalStackedBar100"
2124
- ? "stacked100"
2125
- : type === "stackedBar" || type === "horizontalStackedBar"
2126
- ? "stacked"
2127
- : undefined);
2128
- return {
2129
- ...(orientation ? { orientation } : {}),
2130
- ...(["grouped", "stacked", "stacked100"].includes(groupMode) ? { group_mode: groupMode } : {})
2131
- };
2132
- }
2133
- function chartWidgetPayload(chart, rows, source, snapshot, sourceQueryText) {
2134
- const encodedPayload = chartHasEncodingSpec(chart) ? chartWidgetPayloadFromEncodings(chart, rows, source, snapshot, sourceQueryText) : null;
2135
- if (encodedPayload)
2136
- return encodedPayload;
2137
- return null;
2138
- }
2139
- function TableContent({ allowColumnResize = true, columnWidths, density, filters, onColumnWidthsChange, selectedFilters, snapshot, table, isFullscreen = false }) {
2140
- const rows = filterRowsForDataset(getRows(snapshot, table.dataset), table.dataset, filters, selectedFilters, table.columns.map((column) => column.field));
2141
- const [page, setPage] = useState(0);
2142
- const [sortState, setSortState] = useState(null);
2143
- const [isColumnResizing, setIsColumnResizing] = useState(false);
2144
- const headerCellRefs = useRef({});
2145
- const tableWrapRef = useRef(null);
2146
- const sortedRows = useMemo(() => {
2147
- if (!sortState)
2148
- return rows;
2149
- return [...rows].sort((a, b) => compareTableValues(a, b, sortState.field, sortState.direction));
2150
- }, [rows, sortState]);
2151
- const pageSize = isFullscreen ? Math.max(1, sortedRows.length) : TABLE_CARD_PAGE_SIZE;
2152
- const totalPages = Math.max(1, Math.ceil(sortedRows.length / pageSize));
2153
- const currentPage = Math.min(page, totalPages - 1);
2154
- const shouldShowPagination = rows.length > 0 && !isFullscreen && totalPages > 1;
2155
- const shouldShowCount = rows.length > 0 && shouldShowPagination;
2156
- const shouldShowFooter = shouldShowCount || shouldShowPagination;
2157
- const resultCountLabel = `${sortedRows.length.toLocaleString()} ${sortedRows.length === 1 ? "result" : "results"}`;
2158
- const visibleRows = isFullscreen
2159
- ? sortedRows
2160
- : sortedRows.slice(currentPage * pageSize, currentPage * pageSize + pageSize);
2161
- const estimatedColumnWidths = useMemo(() => estimateTableColumnWidths(table, rows, density), [density, rows, table]);
2162
- const activeColumnWidths = useMemo(() => {
2163
- return Object.fromEntries(table.columns.map((column) => [
2164
- column.field,
2165
- clamp(Math.round(columnWidths[column.field] ?? estimatedColumnWidths[column.field] ?? TABLE_COLUMN_DEFAULT_WIDTH), TABLE_COLUMN_MIN_WIDTH, TABLE_COLUMN_MAX_WIDTH)
2166
- ]));
2167
- }, [columnWidths, estimatedColumnWidths, table.columns]);
2168
- const tablePixelWidth = table.columns.reduce((total, column) => total + activeColumnWidths[column.field], 0);
2169
- const tableStyle = {
2170
- minWidth: `${tablePixelWidth}px`,
2171
- tableLayout: "fixed",
2172
- width: `${tablePixelWidth}px`
2173
- };
2174
- useEffect(() => {
2175
- setPage(0);
2176
- }, [isFullscreen, rows.length, sortState]);
2177
- useLayoutEffect(() => {
2178
- if (tableWrapRef.current) {
2179
- tableWrapRef.current.scrollLeft = 0;
2180
- }
2181
- }, [isFullscreen, rows.length, table.id]);
2182
- function toggleSort(field) {
2183
- setSortState((current) => {
2184
- if (current?.field !== field)
2185
- return { direction: "asc", field };
2186
- return { direction: current.direction === "asc" ? "desc" : "asc", field };
2187
- });
2188
- }
2189
- function measuredColumnWidths() {
2190
- return Object.fromEntries(table.columns.map((column) => {
2191
- const measuredWidth = headerCellRefs.current[column.field]?.getBoundingClientRect().width;
2192
- const width = measuredWidth ?? activeColumnWidths[column.field] ?? TABLE_COLUMN_DEFAULT_WIDTH;
2193
- return [
2194
- column.field,
2195
- clamp(Math.round(width), TABLE_COLUMN_MIN_WIDTH, TABLE_COLUMN_MAX_WIDTH)
2196
- ];
2197
- }));
2198
- }
2199
- function resizeColumnBy(field, delta, shouldPersist) {
2200
- const baseWidths = { ...activeColumnWidths, ...measuredColumnWidths(), ...columnWidths };
2201
- const currentWidth = baseWidths[field] ?? TABLE_COLUMN_DEFAULT_WIDTH;
2202
- onColumnWidthsChange(table.id, {
2203
- ...baseWidths,
2204
- [field]: clamp(Math.round(currentWidth + delta), TABLE_COLUMN_MIN_WIDTH, TABLE_COLUMN_MAX_WIDTH)
2205
- }, { persist: shouldPersist });
2206
- }
2207
- function startColumnResize(event, field) {
2208
- event.preventDefault();
2209
- event.stopPropagation();
2210
- const baseWidths = { ...activeColumnWidths, ...measuredColumnWidths(), ...columnWidths };
2211
- const startWidth = baseWidths[field] ?? TABLE_COLUMN_DEFAULT_WIDTH;
2212
- const startX = event.clientX;
2213
- let latestWidths = baseWidths;
2214
- onColumnWidthsChange(table.id, baseWidths, { persist: false });
2215
- setIsColumnResizing(true);
2216
- document.body.style.cursor = "col-resize";
2217
- document.body.style.userSelect = "none";
2218
- function handlePointerMove(moveEvent) {
2219
- const nextWidth = clamp(Math.round(startWidth + moveEvent.clientX - startX), TABLE_COLUMN_MIN_WIDTH, TABLE_COLUMN_MAX_WIDTH);
2220
- latestWidths = { ...baseWidths, [field]: nextWidth };
2221
- onColumnWidthsChange(table.id, latestWidths, { persist: false });
2222
- }
2223
- function finishResize() {
2224
- window.removeEventListener("pointermove", handlePointerMove);
2225
- window.removeEventListener("pointerup", finishResize);
2226
- window.removeEventListener("pointercancel", finishResize);
2227
- document.body.style.cursor = "";
2228
- document.body.style.userSelect = "";
2229
- setIsColumnResizing(false);
2230
- onColumnWidthsChange(table.id, latestWidths, { persist: true });
2231
- }
2232
- window.addEventListener("pointermove", handlePointerMove);
2233
- window.addEventListener("pointerup", finishResize);
2234
- window.addEventListener("pointercancel", finishResize);
2235
- }
2236
- function handleResizeHandleKeyDown(event, field) {
2237
- if (event.key !== "ArrowLeft" && event.key !== "ArrowRight")
2238
- return;
2239
- event.preventDefault();
2240
- event.stopPropagation();
2241
- resizeColumnBy(field, event.key === "ArrowRight" ? TABLE_COLUMN_KEYBOARD_STEP : -TABLE_COLUMN_KEYBOARD_STEP, true);
2242
- }
2243
- return (<>
2244
- {rows.length ? (<div className={`table-wrap table-density-${density} ${isFullscreen ? "fullscreen" : ""}`} ref={tableWrapRef}>
2245
- <div className="table-scroll-content">
2246
- <table className={`data-table data-table-${density} data-table-resizable ${isColumnResizing ? "is-column-resizing" : ""}`} style={tableStyle}>
2247
- <colgroup>
2248
- {table.columns.map((column) => (<col key={column.field} style={{ width: `${activeColumnWidths[column.field]}px` }}/>))}
2249
- </colgroup>
2250
- <thead>
2251
- <tr>
2252
- {table.columns.map((column) => {
2253
- const isSorted = sortState?.field === column.field;
2254
- const format = tableColumnFormat(column);
2255
- const isNumericColumn = isNumericTableColumn(column, rows);
2256
- const isCenteredColumn = column.align === "center";
2257
- const SortIcon = isSorted ? (sortState.direction === "asc" ? ArrowUp : ArrowDown) : null;
2258
- return (<th aria-sort={isSorted
2259
- ? sortState.direction === "asc"
2260
- ? "ascending"
2261
- : "descending"
2262
- : "none"} key={column.field} ref={(element) => {
2263
- headerCellRefs.current[column.field] = element;
2264
- }} className={isNumericColumn ? "table-header-number" : isCenteredColumn ? "center" : undefined} style={{ width: `${activeColumnWidths[column.field]}px` }}>
2265
- <button className="table-sort-button" onClick={() => toggleSort(column.field)} type="button">
2266
- <span>{column.label}</span>
2267
- {SortIcon ? <SortIcon aria-hidden="true" size={14} strokeWidth={2}/> : null}
2268
- </button>
2269
- {allowColumnResize ? (<button aria-label={`Resize ${column.label} column`} className="table-column-resize-handle" onKeyDown={(event) => handleResizeHandleKeyDown(event, column.field)} onPointerDown={(event) => startColumnResize(event, column.field)} title={`Resize ${column.label} column`} type="button"/>) : null}
2270
- </th>);
2271
- })}
2272
- </tr>
2273
- </thead>
2274
- <tbody>
2275
- {visibleRows.map((row, rowIndex) => (<tr key={`${currentPage}-${rowIndex}`}>
2276
- {table.columns.map((column) => {
2277
- const value = row[column.field];
2278
- const format = tableColumnFormat(column);
2279
- const isNumericColumn = isNumericTableColumn(column, rows);
2280
- const isCenteredColumn = column.align === "center";
2281
- const className = [
2282
- isNumericColumn ? "table-cell-number" : "",
2283
- isCenteredColumn ? "center" : "",
2284
- tableCellMovementClass(column, value)
2285
- ].filter(Boolean).join(" ") || undefined;
2286
- return (<td className={className} key={column.field}>
2287
- {formatTableCellValue(column, value)}
2288
- </td>);
2289
- })}
2290
- </tr>))}
2291
- </tbody>
2292
- </table>
2293
- </div>
2294
- </div>) : (<div className="empty-state">No rows match the selected filters.</div>)}
2295
- {shouldShowFooter ? (<div className="table-pagination">
2296
- {shouldShowCount ? <span className="table-result-count">{resultCountLabel}</span> : null}
2297
- {shouldShowPagination ? (<div className="table-page-control">
2298
- <span>
2299
- Page {currentPage + 1} of {totalPages}
2300
- </span>
2301
- <div className="table-page-buttons">
2302
- <button aria-label="Previous page" className="table-arrow-button" disabled={currentPage === 0} onClick={() => setPage((nextPage) => Math.max(0, nextPage - 1))} type="button">
2303
- <ChevronLeft aria-hidden="true" size={16} strokeWidth={2}/>
2304
- </button>
2305
- <button aria-label="Next page" className="table-arrow-button" disabled={currentPage >= totalPages - 1} onClick={() => setPage((nextPage) => Math.min(totalPages - 1, nextPage + 1))} type="button">
2306
- <ChevronRight aria-hidden="true" size={16} strokeWidth={2}/>
2307
- </button>
2308
- </div>
2309
- </div>) : null}
2310
- </div>) : null}
2311
- </>);
2312
- }
2313
- function DataTable({ columnWidths, filters, isEditMode, isMenuOpen, layout, manifest, onColumnWidthsChange, onDeleteBlock, onMenuOpenChange, onModalOpen, onRequestEditMode, onTextChange, selectedFilters, snapshot, table, textOverride }) {
2314
- const tableDensity = table.density ?? (manifest?.surface === "report" ? "spacious" : "dense");
2315
- const displayHeaderMarkdown = textOverride?.headerMarkdown ?? composeTableHeaderMarkdown(table);
2316
- const displayTitle = markdownFirstLine(displayHeaderMarkdown, table.title);
2317
- const { closeMenu, fixedMenuStyle, handleMenuButtonKeyDown, handleMenuKeyDown, menuButtonRef, menuMotionClass, menuRef, toggleMenu, shouldRenderMenu } = useDashboardMenu(isMenuOpen, onMenuOpenChange);
2318
- const menuItem = (label, icon, onClick, tone = "default") => (<button className={`viz-card-menu-item ${tone === "danger" ? "viz-card-menu-item-danger" : ""}`.trim()} key={label} onClick={() => {
2319
- onClick();
2320
- closeMenu();
2321
- }} role="menuitem" type="button">
2322
- <span aria-hidden="true" className="viz-card-menu-icon">
2323
- {icon}
2324
- </span>
2325
- <span>{label}</span>
2326
- </button>);
2327
- return (<section className={`panel table-panel table-card ${layout === "half" ? "" : "layout-full"}`}>
2328
- <PanelHeader action={<div className="viz-card-actions" data-image-export-exclude="true" ref={menuRef}>
2329
- <button aria-expanded={isMenuOpen} aria-label={`Open options for ${table.title}`} className="viz-card-menu-button viz-card__no-drag" onClick={(event) => {
2330
- event.stopPropagation();
2331
- toggleMenu();
2332
- }} onKeyDown={handleMenuButtonKeyDown} ref={menuButtonRef} type="button">
2333
- <Ellipsis aria-hidden="true" size={18} strokeWidth={2}/>
2334
- </button>
2335
- {shouldRenderMenu ? (<div className={`viz-card-menu menu-surface ${menuMotionClass}`} onKeyDown={handleMenuKeyDown} role="menu" style={fixedMenuStyle}>
2336
- {menuItem("View data source", <Database size={18} strokeWidth={2}/>, () => onModalOpen({ kind: "source", table }))}
2337
- {menuItem("View fullscreen", <Expand size={18} strokeWidth={2}/>, () => onModalOpen({ kind: "fullscreen", table }))}
2338
- {onDeleteBlock ? menuItem("Delete", <Trash2 size={18} strokeWidth={2}/>, onDeleteBlock, "danger") : null}
2339
- </div>) : null}
2340
- </div>} subtitle={table.subtitle} title={displayTitle} titleRowClassName="table-card__drag-handle">
2341
- <RichMarkdown ariaLabel={`Edit markdown header for ${table.title}`} className="editable-cell-header" isEditMode={isEditMode} markdown={displayHeaderMarkdown} onMarkdownChange={(nextMarkdown) => onTextChange(table.id, { headerMarkdown: nextMarkdown })} onRequestEditMode={onRequestEditMode} placeholder={composeTableHeaderMarkdown(table)} variant="cellHeader"/>
2342
- </PanelHeader>
2343
- <TableContent columnWidths={columnWidths} density={tableDensity} filters={filters} onColumnWidthsChange={onColumnWidthsChange} selectedFilters={selectedFilters} snapshot={snapshot} table={table}/>
2344
- </section>);
2345
- }
2346
- function TableModalDialog({ activeFilters, columnWidths, filters, kind, manifest, onColumnWidthsChange, onClose, selectedFilters, snapshot, table }) {
2347
- const dialogRef = useRef(null);
2348
- const source = sourceForTable(table, manifest?.sources ?? []);
2349
- const title = kind === "fullscreen" ? table.title : "Data source";
2350
- const sourceQuery = sourceQueryFromSourceSpec(source);
2351
- const previewRows = filterRowsForDataset(getRows(snapshot, table.dataset), table.dataset, filters, selectedFilters, table.columns.map((column) => column.field));
2352
- const buildDetails = sourceBuildDetails({
2353
- activeFilters,
2354
- columns: table.columns,
2355
- dataset: table.dataset,
2356
- source,
2357
- sourceQuery,
2358
- snapshot
2359
- });
2360
- useModalScrollLock(kind === "source");
2361
- useEffect(() => {
2362
- const dialog = dialogRef.current;
2363
- if (dialog && !dialog.open) {
2364
- dialog.showModal();
2365
- }
2366
- }, []);
2367
- return (<dialog aria-labelledby="table-modal-title" className={`native-modal ${kind === "source" ? "source-modal" : ""}`.trim()} onCancel={onClose} onClick={(event) => {
2368
- if (event.target === event.currentTarget) {
2369
- event.currentTarget.close();
2370
- }
2371
- }} onClose={onClose} ref={dialogRef}>
2372
- <section className={`modal-panel ${kind === "source" ? "source-modal-panel" : ""}`.trim()}>
2373
- <div className="modal-header">
2374
- <div>
2375
- <h2 id="table-modal-title">{title}</h2>
2376
- {kind === "fullscreen" && source?.label ? <p>{source.label}</p> : null}
2377
- </div>
2378
- <button aria-label={`Close ${kind === "source" ? "data source" : "fullscreen table"}`} className="modal-close-button" onClick={() => dialogRef.current?.close()} type="button">
2379
- <X aria-hidden="true" size={20} strokeWidth={2}/>
2380
- </button>
2381
- </div>
2382
- {kind === "fullscreen" ? (<TableContent columnWidths={columnWidths} density={table.density ?? (manifest?.surface === "report" ? "spacious" : "dense")} filters={filters} isFullscreen onColumnWidthsChange={onColumnWidthsChange} selectedFilters={selectedFilters} snapshot={snapshot} table={table}/>) : (<DataSourceDetails details={buildDetails} source={source} sourceQuery={sourceQuery}>
2383
- <SourceDataTable columns={table.columns} dataset={table.dataset} density={table.density ?? (manifest?.surface === "report" ? "spacious" : "dense")} rows={previewRows}/>
2384
- </DataSourceDetails>)}
2385
- </section>
2386
- </dialog>);
2387
- }
2388
- function ReportTextBlock({ block, isEditMode, isMenuOpen, onCopyResult, onDeleteBlock, onMenuOpenChange, onRequestEditMode, onTextChange, textOverride }) {
2389
- const cardRef = useRef(null);
2390
- const toneClass = `report-block-${block.type}`;
2391
- const blockMarkdown = composeBlockMarkdown(block, textOverride);
2392
- const { closeMenu, fixedMenuStyle, handleMenuButtonKeyDown, handleMenuKeyDown, menuButtonRef, menuMotionClass, menuRef, toggleMenu, shouldRenderMenu } = useDashboardMenu(isMenuOpen, onMenuOpenChange);
2393
- const { getPreparedImageBlob, preparedImageExportStatus, prepareImageExport, resetPreparedImageExport } = usePreparedImageExport(cardRef);
2394
- async function handleCopyMarkdown() {
2395
- try {
2396
- await copyTextToClipboard(blockMarkdown.trim());
2397
- onCopyResult("Copied markdown.");
2398
- }
2399
- catch (error) {
2400
- onCopyResult(error instanceof Error ? error.message : "Failed to copy markdown.", true);
2401
- }
2402
- }
2403
- function prepareImageExportQuietly(force = false) {
2404
- if (!shouldOfferImageClipboardCopy())
2405
- return;
2406
- const prepared = prepareImageExport({ force });
2407
- if (prepared)
2408
- void prepared.promise.catch(() => undefined);
2409
- }
2410
- async function handleCopyAsImage() {
2411
- if (!cardRef.current)
2412
- return;
2413
- try {
2414
- const copyResult = await copyElementAsImage(cardRef.current, getPreparedImageBlob());
2415
- resetPreparedImageExport();
2416
- onCopyResult(imageCopySuccessMessage("Copied text block as image.", copyResult));
2417
- }
2418
- catch (error) {
2419
- onCopyResult(error instanceof Error ? error.message : "Failed to copy image.", true);
2420
- }
2421
- }
2422
- const menuItem = (label, icon, onClick, tone = "default", onPrepare, disabled = false) => (<button className={`viz-card-menu-item ${tone === "danger" ? "viz-card-menu-item-danger" : ""}`.trim()} disabled={disabled} key={label} onFocus={onPrepare} onClick={() => {
2423
- void onClick();
2424
- closeMenu();
2425
- }} onPointerEnter={onPrepare} role="menuitem" type="button">
2426
- <span aria-hidden="true" className="viz-card-menu-icon">
2427
- {icon}
2428
- </span>
2429
- <span>{label}</span>
2430
- </button>);
2431
- return (<section className={`panel report-block report-markdown-block ${toneClass}`} id={block.id} ref={cardRef}>
2432
- <div className="viz-card-actions" data-image-export-exclude="true" ref={menuRef}>
2433
- <button aria-expanded={isMenuOpen} aria-label={`Open options for ${markdownFirstLine(blockMarkdown, "Text block")}`} className="viz-card-menu-button viz-card__no-drag" onClick={(event) => {
2434
- event.stopPropagation();
2435
- const nextIsMenuOpen = toggleMenu();
2436
- if (nextIsMenuOpen) {
2437
- prepareImageExportQuietly(true);
2438
- }
2439
- else {
2440
- resetPreparedImageExport();
2441
- }
2442
- }} onFocus={() => prepareImageExportQuietly()} onKeyDown={handleMenuButtonKeyDown} onPointerEnter={() => prepareImageExportQuietly()} ref={menuButtonRef} type="button">
2443
- <Ellipsis aria-hidden="true" size={18} strokeWidth={2}/>
2444
- </button>
2445
- {shouldRenderMenu ? (<div className={`viz-card-menu viz-card__no-drag menu-surface ${menuMotionClass}`} onKeyDown={handleMenuKeyDown} role="menu" style={fixedMenuStyle}>
2446
- {menuItem("Copy markdown", <Copy size={18} strokeWidth={2}/>, handleCopyMarkdown)}
2447
- {shouldOfferImageClipboardCopy()
2448
- ? menuItem("Copy as image", <Camera size={18} strokeWidth={2}/>, handleCopyAsImage, "default", prepareImageExportQuietly, preparedImageExportStatus === "pending")
2449
- : null}
2450
- {menuItem("Delete", <Trash2 size={18} strokeWidth={2}/>, onDeleteBlock, "danger")}
2451
- </div>) : null}
2452
- </div>
2453
- <div className="report-block-body markdown-body">
2454
- <RichMarkdown ariaLabel={`Edit markdown for ${block.type}`} className="report-markdown-editor" isEditMode={isEditMode} markdown={blockMarkdown} minRows={Math.max(2, Math.min(6, blockMarkdown.split(/\r?\n/).length))} onMarkdownChange={(nextMarkdown) => onTextChange(block.id, { bodyMarkdown: nextMarkdown })} onRequestEditMode={onRequestEditMode} placeholder={composeBlockMarkdown(block)} variant="reportBlock"/>
2455
- </div>
2456
- </section>);
2457
- }
2458
- function ReportHtmlBlock({ block, htmlOverride, isEditMode, isMenuOpen, onHtmlChange, onCopyResult, onDeleteBlock, onMenuOpenChange }) {
2459
- const html = composeBlockHtml(block, htmlOverride);
2460
- const title = block.id || "HTML block";
2461
- const { closeMenu, fixedMenuStyle, handleMenuButtonKeyDown, handleMenuKeyDown, menuButtonRef, menuMotionClass, menuRef, toggleMenu, shouldRenderMenu } = useDashboardMenu(isMenuOpen, onMenuOpenChange);
2462
- const frameRef = useRef(null);
2463
- const resizeObserverRef = useRef(null);
2464
- const [frameHeight, setFrameHeight] = useState(0);
2465
- const updateFrameHeight = useCallback(() => {
2466
- const nextHeight = measureHtmlFrameHeight(frameRef.current);
2467
- if (nextHeight > 0)
2468
- setFrameHeight(nextHeight);
2469
- }, []);
2470
- const handleFrameLoad = useCallback(() => {
2471
- resizeObserverRef.current?.disconnect();
2472
- const frameDocument = frameRef.current?.contentDocument;
2473
- if (frameDocument && typeof ResizeObserver !== "undefined") {
2474
- const observer = new ResizeObserver(updateFrameHeight);
2475
- if (frameDocument.documentElement)
2476
- observer.observe(frameDocument.documentElement);
2477
- if (frameDocument.body)
2478
- observer.observe(frameDocument.body);
2479
- resizeObserverRef.current = observer;
2480
- }
2481
- updateFrameHeight();
2482
- }, [updateFrameHeight]);
2483
- useEffect(() => {
2484
- setFrameHeight(0);
2485
- }, [html]);
2486
- useEffect(() => {
2487
- return () => resizeObserverRef.current?.disconnect();
2488
- }, []);
2489
- async function handleCopyHtml() {
2490
- try {
2491
- await copyTextToClipboard(html);
2492
- onCopyResult("Copied HTML.");
2493
- }
2494
- catch (error) {
2495
- onCopyResult(error instanceof Error ? error.message : "Failed to copy HTML.", true);
2496
- }
2497
- }
2498
- const menuItem = (label, icon, onClick, tone = "default") => (<button className={`viz-card-menu-item ${tone === "danger" ? "viz-card-menu-item-danger" : ""}`.trim()} key={label} onClick={() => {
2499
- void onClick();
2500
- closeMenu();
2501
- }} role="menuitem" type="button">
2502
- <span aria-hidden="true" className="viz-card-menu-icon">
2503
- {icon}
2504
- </span>
2505
- <span>{label}</span>
2506
- </button>);
2507
- return (<section className="report-block report-html-block" id={block.id}>
2508
- <div className="viz-card-actions" data-image-export-exclude="true" ref={menuRef}>
2509
- <button aria-expanded={isMenuOpen} aria-label={`Open options for ${title}`} className="viz-card-menu-button viz-card__no-drag" onClick={(event) => {
2510
- event.stopPropagation();
2511
- toggleMenu();
2512
- }} onKeyDown={handleMenuButtonKeyDown} ref={menuButtonRef} type="button">
2513
- <Ellipsis aria-hidden="true" size={18} strokeWidth={2}/>
2514
- </button>
2515
- {shouldRenderMenu ? (<div className={`viz-card-menu viz-card__no-drag menu-surface ${menuMotionClass}`} onKeyDown={handleMenuKeyDown} role="menu" style={fixedMenuStyle}>
2516
- {menuItem("Copy HTML", <Copy size={18} strokeWidth={2}/>, handleCopyHtml)}
2517
- {menuItem("Delete", <Trash2 size={18} strokeWidth={2}/>, onDeleteBlock, "danger")}
2518
- </div>) : null}
2519
- </div>
2520
- {isEditMode ? (<textarea aria-label={`Edit HTML for ${title}`} className="report-html-editor" onChange={(event) => onHtmlChange(block.id, { html: event.target.value })} spellCheck={false} value={html}/>) : (<iframe className="report-html-frame" onLoad={handleFrameLoad} ref={frameRef} sandbox="allow-same-origin" srcDoc={sandboxedReportHtml(html)} style={frameHeight ? { height: `${frameHeight}px` } : undefined} title={title}/>)}
2521
- </section>);
2522
- }
2523
- function ReportMetricStripBlock({ cards, filters, id, isMenuOpen, onCopyResult, onDeleteBlock, onMenuOpenChange, selectedFilters, snapshot }) {
2524
- const cardRef = useRef(null);
2525
- const { closeMenu, fixedMenuStyle, handleMenuButtonKeyDown, handleMenuKeyDown, menuButtonRef, menuMotionClass, menuRef, toggleMenu, shouldRenderMenu } = useDashboardMenu(isMenuOpen, onMenuOpenChange);
2526
- const { getPreparedImageBlob, preparedImageExportStatus, prepareImageExport, resetPreparedImageExport } = usePreparedImageExport(cardRef);
2527
- function prepareImageExportQuietly(force = false) {
2528
- if (!shouldOfferImageClipboardCopy())
2529
- return;
2530
- const prepared = prepareImageExport({ force });
2531
- if (prepared)
2532
- void prepared.promise.catch(() => undefined);
2533
- }
2534
- async function handleCopyAsImage() {
2535
- if (!cardRef.current)
2536
- return;
2537
- try {
2538
- const copyResult = await copyElementAsImage(cardRef.current, getPreparedImageBlob());
2539
- resetPreparedImageExport();
2540
- onCopyResult(imageCopySuccessMessage("Copied key metrics as image.", copyResult));
2541
- }
2542
- catch (error) {
2543
- onCopyResult(error instanceof Error ? error.message : "Failed to copy image.", true);
2544
- }
2545
- }
2546
- const menuItem = (label, icon, onClick, tone = "default", onPrepare, disabled = false) => (<button className={`viz-card-menu-item ${tone === "danger" ? "viz-card-menu-item-danger" : ""}`.trim()} disabled={disabled} key={label} onFocus={onPrepare} onClick={() => {
2547
- void onClick();
2548
- closeMenu();
2549
- }} onPointerEnter={onPrepare} role="menuitem" type="button">
2550
- <span aria-hidden="true" className="viz-card-menu-icon">
2551
- {icon}
2552
- </span>
2553
- <span>{label}</span>
2554
- </button>);
2555
- return (<section className="report-metric-strip-block" id={id} ref={cardRef}>
2556
- <div className="viz-card-actions" data-image-export-exclude="true" ref={menuRef}>
2557
- <button aria-expanded={isMenuOpen} aria-label="Open options for key metrics" className="viz-card-menu-button viz-card__no-drag" onClick={(event) => {
2558
- event.stopPropagation();
2559
- const nextIsMenuOpen = toggleMenu();
2560
- if (nextIsMenuOpen) {
2561
- prepareImageExportQuietly(true);
2562
- }
2563
- else {
2564
- resetPreparedImageExport();
2565
- }
2566
- }} onFocus={() => prepareImageExportQuietly()} onKeyDown={handleMenuButtonKeyDown} onPointerEnter={() => prepareImageExportQuietly()} ref={menuButtonRef} type="button">
2567
- <Ellipsis aria-hidden="true" size={18} strokeWidth={2}/>
2568
- </button>
2569
- {shouldRenderMenu ? (<div className={`viz-card-menu viz-card__no-drag menu-surface ${menuMotionClass}`} onKeyDown={handleMenuKeyDown} role="menu" style={fixedMenuStyle}>
2570
- {shouldOfferImageClipboardCopy()
2571
- ? menuItem("Copy as image", <Camera size={18} strokeWidth={2}/>, handleCopyAsImage, "default", prepareImageExportQuietly, preparedImageExportStatus === "pending")
2572
- : null}
2573
- {menuItem("Delete", <Trash2 size={18} strokeWidth={2}/>, onDeleteBlock, "danger")}
2574
- </div>) : null}
2575
- </div>
2576
- <KpiStrip cards={cards} filters={filters} selectedFilters={selectedFilters} snapshot={snapshot}/>
2577
- </section>);
2578
- }
2579
- function ReportBlockCard({ accessIssues, block, blockTextOverride, chart, chartSpecOverride, chartTextOverride, chartTypeOverride, columnWidths, filters, isBlockMenuOpen, isChartMenuOpen, isEditMode, isTableMenuOpen, layout, manifest, onBlockMenuOpenChange, onBlockTextChange, onChartTypeChange, onChartMenuOpenChange, onColumnWidthsChange, onDeleteBlock, onChartModalOpen, onCopyResult, onRequestEditMode, onTableMenuOpenChange, onTableModalOpen, onTableTextChange, onTextChange, selectedFilters, snapshot, table, tableTextOverride }) {
2580
- if (block.type === "html") {
2581
- return (<ReportHtmlBlock block={block} htmlOverride={blockTextOverride} isEditMode={isEditMode} isMenuOpen={isBlockMenuOpen} onHtmlChange={onBlockTextChange} onCopyResult={onCopyResult} onDeleteBlock={onDeleteBlock} onMenuOpenChange={onBlockMenuOpenChange}/>);
2582
- }
2583
- if (block.type === "chart" && chart) {
2584
- const overriddenChart = applyChartSpecOverride(chart, chartSpecOverride);
2585
- const chartRows = filterRowsForDataset(getRows(snapshot, overriddenChart.dataset), overriddenChart.dataset, filters, selectedFilters, chartUsedFields(overriddenChart));
2586
- const chartTypeOptions = compatibleChartTypesForArtifactCard(overriddenChart, chartRows);
2587
- const requestedType = chartTypeOverride ?? overriddenChart.type;
2588
- const activeType = chartTypeOptions.some((option) => option.type === requestedType)
2589
- ? requestedType
2590
- : overriddenChart.type;
2591
- const displayChart = withChartType(overriddenChart, activeType);
2592
- const accessIssue = accessIssueForChart(displayChart, accessIssues);
2593
- return (<VizCard accessIssue={accessIssue} chart={displayChart} chartTypeOptions={chartTypeOptions} isEditMode={isEditMode} isMenuOpen={isChartMenuOpen} layout={layout} onChartTypeChange={onChartTypeChange} onCopyResult={onCopyResult} onDeleteBlock={onDeleteBlock} onMenuOpenChange={onChartMenuOpenChange} onModalOpen={onChartModalOpen} onRequestEditMode={onRequestEditMode} onTextChange={onTextChange} textOverride={chartTextOverride}>
2594
- <ChartBody accessIssue={accessIssue} chart={displayChart} filters={filters} layout={layout} selectedFilters={selectedFilters} snapshot={snapshot}/>
2595
- </VizCard>);
2596
- }
2597
- if (block.type === "table" && table) {
2598
- return (<DataTable columnWidths={columnWidths} filters={filters} isEditMode={isEditMode} isMenuOpen={isTableMenuOpen} layout={layout} manifest={manifest} onColumnWidthsChange={onColumnWidthsChange} onDeleteBlock={onDeleteBlock} onMenuOpenChange={onTableMenuOpenChange} onModalOpen={onTableModalOpen} onRequestEditMode={onRequestEditMode} onTextChange={onTableTextChange} selectedFilters={selectedFilters} snapshot={snapshot} table={table} textOverride={tableTextOverride}/>);
2599
- }
2600
- return (<ReportTextBlock block={block} isEditMode={isEditMode} isMenuOpen={isBlockMenuOpen} onCopyResult={onCopyResult} onDeleteBlock={onDeleteBlock} onMenuOpenChange={onBlockMenuOpenChange} onRequestEditMode={onRequestEditMode} onTextChange={onBlockTextChange} textOverride={blockTextOverride}/>);
2601
- }
2602
- const EXPORT_TARGET_LABELS = {
2603
- site: "Publish to Sites",
2604
- html: "Create HTML file",
2605
- pdf: "Create PDF",
2606
- document: "Create Google Doc",
2607
- slides: "Create Google Slides"
2608
- };
2609
- const EXPORT_TARGET_ICONS = {
2610
- site: <Globe aria-hidden="true" size={16} strokeWidth={2}/>,
2611
- html: <FileText aria-hidden="true" size={16} strokeWidth={2}/>,
2612
- pdf: <FileDown aria-hidden="true" size={16} strokeWidth={2}/>,
2613
- document: <FileText aria-hidden="true" size={16} strokeWidth={2}/>,
2614
- slides: <Presentation aria-hidden="true" size={16} strokeWidth={2}/>
2615
- };
2616
- function packageControls(packageInfo) {
2617
- return packageInfo?.controls && typeof packageInfo.controls === "object" ? packageInfo.controls : {};
2618
- }
2619
- function artifactCapabilities(packageInfo) {
2620
- const controls = packageControls(packageInfo);
2621
- const hostedReadOnly = packageInfo?.hostedReadOnly === true || packageInfo?.deliveryMode === "site_creator";
2622
- return {
2623
- canEdit: !hostedReadOnly && controls.edit !== false,
2624
- canPublishHostedLink: !hostedReadOnly && controls.exportHostedLink !== false && controls.hostedLink !== false,
2625
- canExportHtml: controls.html !== false,
2626
- canExportPdf: controls.pdf !== false,
2627
- canExportDocument: controls.document !== false,
2628
- canExportSlides: controls.slides !== false
2629
- };
2630
- }
2631
- function exportTargetsForCapabilities(capabilities) {
2632
- return Object.keys(EXPORT_TARGET_LABELS).filter((target) => {
2633
- if (target === "site")
2634
- return capabilities.canPublishHostedLink;
2635
- if (target === "html")
2636
- return capabilities.canExportHtml;
2637
- if (target === "pdf")
2638
- return capabilities.canExportPdf;
2639
- if (target === "document")
2640
- return capabilities.canExportDocument;
2641
- if (target === "slides")
2642
- return capabilities.canExportSlides;
2643
- return false;
2644
- });
2645
- }
2646
- function appSurfaceLabel(manifest) {
2647
- return manifest?.surface === "report" ? "report" : "dashboard";
2648
- }
2649
- function compactArtifactUrl() {
2650
- try {
2651
- const url = new URL(window.location.href);
2652
- for (const name of ["locale", "deviceType", "unsafeSkipTargetOriginCheck"]) {
2653
- url.searchParams.delete(name);
2654
- }
2655
- return url.toString();
2656
- }
2657
- catch {
2658
- return window.location.href;
2659
- }
2660
- }
2661
- function usefulContextPath(value) {
2662
- const trimmedValue = value?.trim();
2663
- return trimmedValue && trimmedValue !== "tool payload" && !trimmedValue.startsWith("mcp://")
2664
- ? trimmedValue
2665
- : null;
2666
- }
2667
- function promptContext(manifest, snapshot, packageInfo) {
2668
- const packagePath = usefulContextPath(packageInfo?.root);
2669
- const manifestPath = usefulContextPath(packageInfo?.manifestPath);
2670
- const snapshotPath = usefulContextPath(packageInfo?.snapshotPath);
2671
- return [
2672
- `Artifact URL: ${compactArtifactUrl()}`,
2673
- packagePath ? `Package path: ${packagePath}` : null,
2674
- manifestPath ? `Manifest file: ${manifestPath}` : null,
2675
- snapshotPath ? `Snapshot file: ${snapshotPath}` : null,
2676
- `Generated at: ${snapshot?.generatedAt ?? manifest?.generatedAt ?? "unknown"}`
2677
- ]
2678
- .filter((line) => Boolean(line))
2679
- .join("\n");
2680
- }
2681
- function refreshPrompt(manifest, snapshot, packageInfo) {
2682
- const surface = appSurfaceLabel(manifest);
2683
- return `Refresh this ${surface} app using the artifact manifest's declared sources and the latest available time frame.
2684
-
2685
- Inspect the artifact manifest for source details before rerunning. Update the snapshot data and generatedAt metadata, rebuild any static export, and verify the refreshed ${surface} in the in-app browser. Keep the current layout and narrative structure unless the latest data makes a statement incorrect.
2686
-
2687
- ${promptContext(manifest, snapshot, packageInfo)}`;
2688
- }
2689
- function exportPrompt(target, manifest, snapshot, packageInfo) {
2690
- const surface = appSurfaceLabel(manifest);
2691
- const context = promptContext(manifest, snapshot, packageInfo);
2692
- if (target === "site") {
2693
- return `Publish this ${surface} app as a hosted Site Creator link.
2694
-
2695
- Use the current Data Analytics artifact as the source of truth. Create or reuse a Site Creator project for this ${surface}, materialize a Cloudflare Worker-compatible app that serves the current manifest, bounded snapshot, package metadata, and inline-safe source text through /api/manifest, /api/snapshot, /api/package, and /api/source-file, then deploy it through Site Creator. Preserve the rendered layout, charts, tables, source details, and narrative. Use the access scope I explicitly selected. If no access scope has been selected, keep the package local and ask for that publishing decision before deployment. Report the production URL and actual access mode only after successful deployment.
2696
-
2697
- If the local package files are unavailable from the context below, stop and ask for the report package or validated artifact payload rather than publishing an empty or stale report.
2698
-
2699
- ${context}`;
2700
- }
2701
- if (target === "html") {
2702
- return `Export this ${surface} app as a static, portable HTML artifact. Include the content title, narrative, charts, tables, and source details. Omit the interactive top bar and app-only controls from the exported artifact. Verify the HTML before delivery.
2703
-
2704
- ${context}`;
2705
- }
2706
- if (target === "document") {
2707
- return `Use the existing data-analytics:report-to-google-doc workflow to export this ${surface} app as a polished native document artifact. Use the current app content and static HTML export when available, preserve headings, charts, tables, source details, and the executive narrative, then verify the created document.
2708
-
2709
- ${context}`;
2710
- }
2711
- if (target === "slides") {
2712
- return `Use the existing data-analytics:report-to-google-slides workflow to export this ${surface} app as an executive-ready native slides artifact. Preserve the core claims, charts, tables, caveats, and source details, and verify the created deck.
2713
-
2714
- ${context}`;
2715
- }
2716
- return `Use the existing data-analytics:report-to-pdf workflow to create a PDF artifact from this ${surface} app. Use the static HTML/export path when available, preserve the content title, narrative, charts, tables, caveats, and source details, omit interactive top bars, share menus, edit controls, and app-only controls, then verify the PDF before delivery.
2717
-
2718
- ${context}`;
2719
- }
2720
- function setOptionalCodexSearchParam(url, name, value) {
2721
- const trimmedValue = value?.trim();
2722
- if (!trimmedValue)
2723
- return;
2724
- url.searchParams.set(name, trimmedValue);
2725
- }
2726
- function codexPromptUrl(prompt, packageInfo) {
2727
- const url = new URL("codex://threads/new");
2728
- setOptionalCodexSearchParam(url, "prompt", prompt);
2729
- setOptionalCodexSearchParam(url, "originUrl", packageInfo?.originUrl);
2730
- setOptionalCodexSearchParam(url, "path", packageInfo?.root);
2731
- return url.toString();
2732
- }
2733
- function codexHostPromptPayload(prompt, packageInfo) {
2734
- return {
2735
- originUrl: packageInfo?.originUrl,
2736
- path: packageInfo?.root,
2737
- prompt
2738
- };
2739
- }
2740
- function sendCodexPromptToHost(prompt, packageInfo) {
2741
- const hostApi = window.openai;
2742
- const payload = codexHostPromptPayload(prompt, packageInfo);
2743
- const launchers = [hostApi?.sendFollowUpMessage, hostApi?.openCodexPrompt];
2744
- for (const launch of launchers) {
2745
- if (typeof launch !== "function")
2746
- continue;
2747
- try {
2748
- void Promise.resolve(launch.call(hostApi, payload)).catch(() => { });
2749
- return true;
2750
- }
2751
- catch {
2752
- }
2753
- }
2754
- return false;
2755
- }
2756
- function isLocalPreviewHost() {
2757
- return ["localhost", "127.0.0.1", "::1"].includes(window.location.hostname);
2758
- }
2759
- function launchCodexDeepLink(url) {
2760
- if (isLocalPreviewHost())
2761
- return false;
2762
- let linkClicked = false;
2763
- try {
2764
- const link = document.createElement("a");
2765
- link.href = url;
2766
- link.target = "_top";
2767
- link.rel = "noopener noreferrer";
2768
- link.style.display = "none";
2769
- document.body.appendChild(link);
2770
- link.click();
2771
- link.remove();
2772
- linkClicked = true;
2773
- }
2774
- catch {
2775
- }
2776
- try {
2777
- if (window.top === window) {
2778
- window.location.assign(url);
2779
- return true;
2780
- }
2781
- }
2782
- catch {
2783
- }
2784
- return linkClicked;
2785
- }
2786
- function openCodexPrompt(prompt, packageInfo, onCopyResult) {
2787
- const url = codexPromptUrl(prompt, packageInfo);
2788
- const launched = launchCodexDeepLink(url);
2789
- const sentToHost = sendCodexPromptToHost(prompt, packageInfo);
2790
- const openedCodex = sentToHost || launched;
2791
- void copyTextToClipboard(prompt)
2792
- .then(() => {
2793
- onCopyResult(sentToHost
2794
- ? "Started in this chat."
2795
- : openedCodex
2796
- ? "Codex prompt copied. Opening Codex if supported."
2797
- : "Prompt copied. Open Codex and paste it to continue.", false);
2798
- })
2799
- .catch(() => {
2800
- onCopyResult(openedCodex
2801
- ? "Opening Codex if supported, but prompt copy was blocked."
2802
- : "Could not copy the Codex prompt from this preview.", true);
2803
- });
2804
- }
2805
- function AnalyticsTopBarFreshness({ dateLabel, onRefresh, status, statusLabel }) {
2806
- const refreshTitle = dateLabel === "Unknown"
2807
- ? "Refresh using latest available data."
2808
- : `Refresh using latest available data. Last updated ${dateLabel}.`;
2809
- const refreshLabel = dateLabel === "Unknown" ? "Refresh" : dateLabel;
2810
- return (<div className="analytics-top-bar-freshness">
2811
- <button aria-label={refreshTitle} className="top-bar-button top-bar-button-ghost top-bar-refresh-button" onClick={onRefresh} title={refreshTitle} type="button">
2812
- <RefreshCw aria-hidden="true" size={14} strokeWidth={2}/>
2813
- <span>{refreshLabel}</span>
2814
- {statusLabel ? <span className={`snapshot-status ${status}`}>{statusLabel}</span> : null}
2815
- </button>
2816
- </div>);
2817
- }
2818
- function AnalyticsTopBar({ chrome = "full", isEditMode, onCancelEdit, manifest, onCopyResult, onEdit, onRequestFullscreen, onSaveEdit, onTitleChange, packageInfo, snapshot, title }) {
2819
- const [isExportMenuOpen, setIsExportMenuOpen] = useState(false);
2820
- const { closeMenu, fixedMenuStyle, handleMenuButtonKeyDown, handleMenuKeyDown, menuButtonRef, menuMotionClass, menuRef, toggleMenu, shouldRenderMenu } = useDashboardMenu(isExportMenuOpen, setIsExportMenuOpen);
2821
- const capabilities = artifactCapabilities(packageInfo);
2822
- const exportTargets = exportTargetsForCapabilities(capabilities);
2823
- const lastRefresh = formatDate(snapshot?.generatedAt ?? manifest?.generatedAt);
2824
- const statusLabel = snapshotStatusLabel(snapshot?.status);
2825
- const dateLabel = lastRefresh;
2826
- const showStatusLabel = manifest?.surface !== "report" && statusLabel;
2827
- const showActions = chrome === "full";
2828
- const showInlineExpand = chrome === "inline" && typeof onRequestFullscreen === "function";
2829
- function requestRefresh() {
2830
- void openCodexPrompt(refreshPrompt(manifest, snapshot, packageInfo), packageInfo, onCopyResult);
2831
- }
2832
- function requestExport(target) {
2833
- closeMenu();
2834
- void openCodexPrompt(exportPrompt(target, manifest, snapshot, packageInfo), packageInfo, onCopyResult);
2835
- }
2836
- return (<div className="analytics-top-bar" aria-label={`${appSurfaceLabel(manifest)} actions`}>
2837
- <div className="analytics-top-bar-title">
2838
- <EditablePageTitle ariaLabel={`Edit ${appSurfaceLabel(manifest)} title`} isEditMode={isEditMode} onChange={onTitleChange} onRequestEditMode={onEdit} placeholder={composePageTitle(manifest)} readOnly={!showActions || !capabilities.canEdit} title={title}/>
2839
- </div>
2840
- {showInlineExpand ? (<div className="analytics-top-bar-actions">
2841
- <button aria-label={`Expand ${appSurfaceLabel(manifest)} fullscreen`} className="top-bar-button" onClick={onRequestFullscreen} title={`Expand ${appSurfaceLabel(manifest)} fullscreen`} type="button">
2842
- <Expand aria-hidden="true" size={14} strokeWidth={2}/>
2843
- <span>Expand</span>
2844
- </button>
2845
- </div>) : showActions ? (<div className="analytics-top-bar-actions">
2846
- <AnalyticsTopBarFreshness dateLabel={dateLabel} onRefresh={requestRefresh} status={snapshot?.status} statusLabel={showStatusLabel ? statusLabel : null}/>
2847
- {isEditMode && capabilities.canEdit ? (<>
2848
- <button className="top-bar-button" onClick={onCancelEdit} type="button">
2849
- <span>Cancel</span>
2850
- </button>
2851
- <button className="top-bar-button top-bar-button-primary" onClick={onSaveEdit} type="button">
2852
- <span>Save changes</span>
2853
- </button>
2854
- </>) : (<>
2855
- {capabilities.canEdit ? (
2856
- <button className="top-bar-button top-bar-edit-button" onClick={onEdit} type="button">
2857
- <Pencil aria-hidden="true" size={14} strokeWidth={2}/>
2858
- <span>Edit</span>
2859
- </button>
2860
- ): null}
2861
- {exportTargets.length ? (
2862
- <div className="export-menu">
2863
- <button ref={menuButtonRef} aria-expanded={isExportMenuOpen} aria-haspopup="menu" className="top-bar-button" onClick={toggleMenu} onKeyDown={handleMenuButtonKeyDown} type="button">
2864
- <span>Export</span>
2865
- <ChevronDown aria-hidden="true" size={14} strokeWidth={2}/>
2866
- </button>
2867
- {shouldRenderMenu ? (<div ref={menuRef} className={`export-menu-list menu-surface ${menuMotionClass}`} onKeyDown={handleMenuKeyDown} role="menu" style={fixedMenuStyle}>
2868
- {exportTargets.map((target) => (<button className="export-menu-item" key={target} onClick={() => requestExport(target)} role="menuitem" type="button">
2869
- {EXPORT_TARGET_ICONS[target]}
2870
- {EXPORT_TARGET_LABELS[target]}
2871
- </button>))}
2872
- </div>) : null}
2873
- </div>
2874
- ): null}
2875
- </>)}
2876
- </div>) : null}
2877
- </div>);
2878
- }
2879
- export default function App({ displayMode = "fullscreen", onRequestFullscreen } = {}) {
2880
- const [manifest, setManifest] = useState(null);
2881
- const [snapshot, setSnapshot] = useState(null);
2882
- const [packageInfo, setPackageInfo] = useState(null);
2883
- const [error, setError] = useState(null);
2884
- const [selectedFilters, setSelectedFilters] = useState({});
2885
- const [tableColumnWidths, setTableColumnWidths] = useState({});
2886
- const [pageTitle, setPageTitle] = useState("");
2887
- const [chartTextOverrides, setChartTextOverrides] = useState({});
2888
- const [chartSpecOverrides, setChartSpecOverrides] = useState({});
2889
- const [chartTypeOverrides, setChartTypeOverrides] = useState({});
2890
- const [tableTextOverrides, setTableTextOverrides] = useState({});
2891
- const [blockTextOverrides, setBlockTextOverrides] = useState({});
2892
- const [deletedReportBlockIds, setDeletedReportBlockIds] = useState([]);
2893
- const [openMenuChartId, setOpenMenuChartId] = useState(null);
2894
- const [openMenuTableId, setOpenMenuTableId] = useState(null);
2895
- const [openMenuBlockId, setOpenMenuBlockId] = useState(null);
2896
- const [chartModal, setChartModal] = useState(null);
2897
- const [tableModal, setTableModal] = useState(null);
2898
- const [copyMessage, setCopyMessage] = useState(null);
2899
- const [isEditMode, setIsEditMode] = useState(false);
2900
- const [layoutResetKey, setLayoutResetKey] = useState(0);
2901
- const editSnapshotRef = useRef(null);
2902
- const layoutDraftsRef = useRef({ dashboard: null, report: null });
2903
- useEffect(() => {
2904
- async function load() {
2905
- try {
2906
- const [nextManifest, nextSnapshot, nextPackageInfo] = await Promise.all([
2907
- fetchJson("/api/manifest"),
2908
- fetchJson("/api/snapshot"),
2909
- fetchOptionalJson("/api/package")
2910
- ]);
2911
- setManifest(normalizeManifest(nextManifest));
2912
- setSnapshot(normalizeSnapshot(nextSnapshot));
2913
- setPackageInfo(nextPackageInfo);
2914
- }
2915
- catch (loadError) {
2916
- setError(loadError instanceof Error ? loadError.message : "Failed to load report");
2917
- }
2918
- }
2919
- void load();
2920
- }, []);
2921
- const filters = manifest?.filters ?? EMPTY_FILTERS;
2922
- const cards = manifest?.cards ?? EMPTY_CARDS;
2923
- const charts = manifest?.charts ?? EMPTY_CHARTS;
2924
- const tables = manifest?.tables ?? EMPTY_TABLES;
2925
- const reportBlocks = manifest?.blocks ?? EMPTY_REPORT_BLOCKS;
2926
- const globalFilters = useMemo(() => getGlobalFilters(filters, cards, charts, tables), [cards, charts, filters, tables]);
2927
- const accessIssues = snapshot?.accessIssues ?? EMPTY_ACCESS_ISSUES;
2928
- const storageKey = contentLayoutKey(manifest);
2929
- const chartTextStorageKey = chartTextKey(manifest);
2930
- const chartSpecStorageKey = chartSpecKey(manifest);
2931
- const chartTypeStorageKey = chartTypeKey(manifest);
2932
- const pageTitleTextStorageKey = pageTitleTextKey(manifest);
2933
- const tableTextStorageKey = tableTextKey(manifest);
2934
- const blockTextStorageKey = blockTextKey(manifest);
2935
- const deletedReportBlockStorageKey = deletedReportBlocksKey(manifest);
2936
- const tableColumnWidthStorageKey = tableColumnWidthKey(manifest);
2937
- const reportStorageKey = reportContentLayoutKey(manifest);
2938
- const isReport = manifest?.surface === "report";
2939
- const activeSurfaceFilters = isReport ? filters : globalFilters;
2940
- const capabilities = useMemo(() => artifactCapabilities(packageInfo), [packageInfo]);
2941
- const activeEditMode = capabilities.canEdit && isEditMode;
2942
- const requestEditMode = capabilities.canEdit ? beginEditMode : undefined;
2943
- useEffect(() => {
2944
- document.title = pageTitle.trim() || composePageTitle(manifest);
2945
- }, [manifest, pageTitle]);
2946
- useEffect(() => {
2947
- if (!capabilities.canEdit && isEditMode) {
2948
- setIsEditMode(false);
2949
- }
2950
- }, [capabilities.canEdit, isEditMode]);
2951
- const cardsById = useMemo(() => new Map(cards.map((card) => [card.id, card])), [cards]);
2952
- const chartsById = useMemo(() => new Map(charts.map((chart) => [chart.id, chart])), [charts]);
2953
- const tablesById = useMemo(() => new Map(tables.map((table) => [table.id, table])), [tables]);
2954
- const reportGridBlocks = reportBlocks;
2955
- const visibleReportGridBlocks = useMemo(() => {
2956
- if (!deletedReportBlockIds.length)
2957
- return reportGridBlocks;
2958
- const deletedIds = new Set(deletedReportBlockIds);
2959
- return reportGridBlocks.filter((block) => !deletedIds.has(block.id));
2960
- }, [deletedReportBlockIds, reportGridBlocks]);
2961
- useEffect(() => {
2962
- if (!reportGridBlocks.length || !deletedReportBlockStorageKey) {
2963
- setDeletedReportBlockIds([]);
2964
- return;
2965
- }
2966
- const stored = window.localStorage.getItem(deletedReportBlockStorageKey);
2967
- if (!stored) {
2968
- setDeletedReportBlockIds([]);
2969
- return;
2970
- }
2971
- try {
2972
- const parsed = JSON.parse(stored);
2973
- const knownIds = new Set(reportGridBlocks.map((block) => block.id));
2974
- const nextIds = Array.isArray(parsed)
2975
- ? parsed.filter((id) => typeof id === "string" && knownIds.has(id))
2976
- : [];
2977
- setDeletedReportBlockIds(nextIds);
2978
- }
2979
- catch {
2980
- setDeletedReportBlockIds([]);
2981
- }
2982
- }, [deletedReportBlockStorageKey, reportGridBlocks]);
2983
- useEffect(() => {
2984
- if (!tables.length || !tableColumnWidthStorageKey) {
2985
- setTableColumnWidths({});
2986
- return;
2987
- }
2988
- const stored = window.localStorage.getItem(tableColumnWidthStorageKey);
2989
- if (!stored) {
2990
- setTableColumnWidths({});
2991
- return;
2992
- }
2993
- try {
2994
- const parsed = JSON.parse(stored);
2995
- const tableFields = new Map(tables.map((table) => [table.id, new Set(table.columns.map((column) => column.field))]));
2996
- const nextState = {};
2997
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
2998
- for (const [tableId, rawWidths] of Object.entries(parsed)) {
2999
- const fields = tableFields.get(tableId);
3000
- if (!fields || !rawWidths || typeof rawWidths !== "object" || Array.isArray(rawWidths)) {
3001
- continue;
3002
- }
3003
- const nextWidths = {};
3004
- for (const [field, rawWidth] of Object.entries(rawWidths)) {
3005
- const width = typeof rawWidth === "number" ? rawWidth : Number(rawWidth);
3006
- if (fields.has(field) && Number.isFinite(width)) {
3007
- nextWidths[field] = clamp(Math.round(width), TABLE_COLUMN_MIN_WIDTH, TABLE_COLUMN_MAX_WIDTH);
3008
- }
3009
- }
3010
- if (Object.keys(nextWidths).length) {
3011
- nextState[tableId] = nextWidths;
3012
- }
3013
- }
3014
- }
3015
- setTableColumnWidths(nextState);
3016
- }
3017
- catch {
3018
- setTableColumnWidths({});
3019
- }
3020
- }, [tableColumnWidthStorageKey, tables]);
3021
- useEffect(() => {
3022
- const fallbackTitle = composePageTitle(manifest);
3023
- if (!pageTitleTextStorageKey) {
3024
- setPageTitle(fallbackTitle);
3025
- return;
3026
- }
3027
- const storedTitle = window.localStorage.getItem(pageTitleTextStorageKey);
3028
- setPageTitle(storedTitle ?? fallbackTitle);
3029
- }, [manifest, pageTitleTextStorageKey]);
3030
- useEffect(() => {
3031
- if (!charts.length || !chartTextStorageKey)
3032
- return;
3033
- const stored = window.localStorage.getItem(chartTextStorageKey);
3034
- if (!stored) {
3035
- setChartTextOverrides({});
3036
- return;
3037
- }
3038
- try {
3039
- const parsed = JSON.parse(stored);
3040
- const knownIds = new Set(charts.map((chart) => chart.id));
3041
- const nextOverrides = {};
3042
- for (const [chartId, override] of Object.entries(parsed)) {
3043
- if (knownIds.has(chartId)
3044
- && override
3045
- && typeof override === "object"
3046
- && (typeof override.headerMarkdown === "string"
3047
- || typeof override.title === "string"
3048
- || typeof override.subtitle === "string")) {
3049
- nextOverrides[chartId] = {
3050
- ...(typeof override.headerMarkdown === "string" ? { headerMarkdown: override.headerMarkdown } : {}),
3051
- ...(typeof override.title === "string" ? { title: override.title } : {}),
3052
- ...(typeof override.subtitle === "string" ? { subtitle: override.subtitle } : {})
3053
- };
3054
- }
3055
- }
3056
- setChartTextOverrides(nextOverrides);
3057
- }
3058
- catch {
3059
- setChartTextOverrides({});
3060
- }
3061
- }, [chartTextStorageKey, charts]);
3062
- useEffect(() => {
3063
- if (!charts.length || !chartSpecStorageKey) {
3064
- setChartSpecOverrides({});
3065
- return;
3066
- }
3067
- const stored = window.localStorage.getItem(chartSpecStorageKey);
3068
- if (!stored) {
3069
- setChartSpecOverrides({});
3070
- return;
3071
- }
3072
- try {
3073
- const parsed = JSON.parse(stored);
3074
- const chartsByIdForStorage = new Map(charts.map((chart) => [chart.id, chart]));
3075
- const nextOverrides = {};
3076
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
3077
- for (const [chartId, override] of Object.entries(parsed)) {
3078
- const chart = chartsByIdForStorage.get(chartId);
3079
- if (!chart || !override || typeof override !== "object" || Array.isArray(override)) {
3080
- continue;
3081
- }
3082
- const sanitized = {};
3083
- if (sharedIsChartType(override.type)) {
3084
- sanitized.type = override.type;
3085
- }
3086
- const chartFields = new Set(chartUsedFields(chart));
3087
- if (override.encodings && typeof override.encodings === "object" && !Array.isArray(override.encodings)) {
3088
- const sizeEncoding = override.encodings.size;
3089
- if (sizeEncoding && typeof sizeEncoding === "object" && !Array.isArray(sizeEncoding) && typeof sizeEncoding.field === "string" && chartFields.has(sizeEncoding.field)) {
3090
- sanitized.encodings = { ...chart.encodings, size: { ...sizeEncoding, field: sizeEncoding.field } };
3091
- }
3092
- }
3093
- if (override.settings && typeof override.settings === "object" && !Array.isArray(override.settings)) {
3094
- sanitized.settings = {
3095
- ...(override.settings.orientation === "horizontal" || override.settings.orientation === "vertical" ? { orientation: override.settings.orientation } : {}),
3096
- ...(["grouped", "stacked", "stacked100"].includes(override.settings.groupMode) ? { groupMode: override.settings.groupMode } : {}),
3097
- };
3098
- if (!Object.keys(sanitized.settings).length) {
3099
- delete sanitized.settings;
3100
- }
3101
- }
3102
- if (Object.keys(sanitized).length) {
3103
- nextOverrides[chartId] = sanitized;
3104
- }
3105
- }
3106
- }
3107
- setChartSpecOverrides(nextOverrides);
3108
- }
3109
- catch {
3110
- setChartSpecOverrides({});
3111
- }
3112
- }, [chartSpecStorageKey, charts]);
3113
- useEffect(() => {
3114
- if (!charts.length || !chartTypeStorageKey) {
3115
- setChartTypeOverrides({});
3116
- return;
3117
- }
3118
- const stored = window.localStorage.getItem(chartTypeStorageKey);
3119
- if (!stored) {
3120
- setChartTypeOverrides({});
3121
- return;
3122
- }
3123
- try {
3124
- const parsed = JSON.parse(stored);
3125
- const knownIds = new Set(charts.map((chart) => chart.id));
3126
- const nextOverrides = {};
3127
- for (const [chartId, chartType] of Object.entries(parsed)) {
3128
- if (knownIds.has(chartId) && isChartType(chartType)) {
3129
- nextOverrides[chartId] = chartType;
3130
- }
3131
- }
3132
- setChartTypeOverrides(nextOverrides);
3133
- }
3134
- catch {
3135
- setChartTypeOverrides({});
3136
- }
3137
- }, [chartTypeStorageKey, charts]);
3138
- useEffect(() => {
3139
- if (!tables.length || !tableTextStorageKey)
3140
- return;
3141
- const stored = window.localStorage.getItem(tableTextStorageKey);
3142
- if (!stored) {
3143
- setTableTextOverrides({});
3144
- return;
3145
- }
3146
- try {
3147
- const parsed = JSON.parse(stored);
3148
- const knownIds = new Set(tables.map((table) => table.id));
3149
- const nextOverrides = {};
3150
- for (const [tableId, override] of Object.entries(parsed)) {
3151
- if (knownIds.has(tableId)
3152
- && override
3153
- && typeof override === "object"
3154
- && typeof override.headerMarkdown === "string") {
3155
- nextOverrides[tableId] = { headerMarkdown: override.headerMarkdown };
3156
- }
3157
- }
3158
- setTableTextOverrides(nextOverrides);
3159
- }
3160
- catch {
3161
- setTableTextOverrides({});
3162
- }
3163
- }, [tableTextStorageKey, tables]);
3164
- useEffect(() => {
3165
- if (!reportGridBlocks.length || !blockTextStorageKey)
3166
- return;
3167
- const stored = window.localStorage.getItem(blockTextStorageKey);
3168
- if (!stored) {
3169
- setBlockTextOverrides({});
3170
- return;
3171
- }
3172
- try {
3173
- const parsed = JSON.parse(stored);
3174
- const knownIds = new Set(reportGridBlocks.map((block) => block.id));
3175
- const nextOverrides = {};
3176
- for (const [blockId, override] of Object.entries(parsed)) {
3177
- if (knownIds.has(blockId) && override && typeof override === "object") {
3178
- const nextOverride = {
3179
- ...(visibleString(override.bodyMarkdown) ? { bodyMarkdown: override.bodyMarkdown } : {}),
3180
- ...(visibleString(override.html) ? { html: override.html } : {})
3181
- };
3182
- if (Object.keys(nextOverride).length)
3183
- nextOverrides[blockId] = nextOverride;
3184
- }
3185
- }
3186
- setBlockTextOverrides(nextOverrides);
3187
- }
3188
- catch {
3189
- setBlockTextOverrides({});
3190
- }
3191
- }, [blockTextStorageKey, reportGridBlocks]);
3192
- const filterDefaults = useMemo(() => {
3193
- return Object.fromEntries(activeSurfaceFilters.map((filter) => [filter.id, filter.defaultValue ?? "all"]));
3194
- }, [activeSurfaceFilters]);
3195
- useEffect(() => {
3196
- setSelectedFilters((current) => ({ ...filterDefaults, ...current }));
3197
- }, [filterDefaults]);
3198
- useEffect(() => {
3199
- if (!copyMessage)
3200
- return;
3201
- const timeout = window.setTimeout(() => setCopyMessage(null), 2600);
3202
- return () => window.clearTimeout(timeout);
3203
- }, [copyMessage]);
3204
- function persistEditableState() {
3205
- if (pageTitleTextStorageKey) {
3206
- window.localStorage.setItem(pageTitleTextStorageKey, pageTitle);
3207
- }
3208
- if (chartTextStorageKey) {
3209
- window.localStorage.setItem(chartTextStorageKey, JSON.stringify(chartTextOverrides));
3210
- }
3211
- if (chartSpecStorageKey) {
3212
- window.localStorage.setItem(chartSpecStorageKey, JSON.stringify(chartSpecOverrides));
3213
- }
3214
- if (chartTypeStorageKey) {
3215
- window.localStorage.setItem(chartTypeStorageKey, JSON.stringify(chartTypeOverrides));
3216
- }
3217
- if (tableTextStorageKey) {
3218
- window.localStorage.setItem(tableTextStorageKey, JSON.stringify(tableTextOverrides));
3219
- }
3220
- if (blockTextStorageKey) {
3221
- window.localStorage.setItem(blockTextStorageKey, JSON.stringify(blockTextOverrides));
3222
- }
3223
- if (deletedReportBlockStorageKey) {
3224
- window.localStorage.setItem(deletedReportBlockStorageKey, JSON.stringify(deletedReportBlockIds));
3225
- }
3226
- if (tableColumnWidthStorageKey) {
3227
- window.localStorage.setItem(tableColumnWidthStorageKey, JSON.stringify(tableColumnWidths));
3228
- }
3229
- if (storageKey && layoutDraftsRef.current.dashboard) {
3230
- window.localStorage.setItem(storageKey, JSON.stringify(layoutDraftsRef.current.dashboard));
3231
- }
3232
- if (reportStorageKey && layoutDraftsRef.current.report) {
3233
- window.localStorage.setItem(reportStorageKey, JSON.stringify(layoutDraftsRef.current.report));
3234
- }
3235
- }
3236
- function closeInlineMenus() {
3237
- setOpenMenuBlockId(null);
3238
- setOpenMenuChartId(null);
3239
- setOpenMenuTableId(null);
3240
- }
3241
- function beginEditMode() {
3242
- if (isEditMode)
3243
- return;
3244
- editSnapshotRef.current = {
3245
- blockTextOverrides: cloneSerializable(blockTextOverrides),
3246
- chartSpecOverrides: cloneSerializable(chartSpecOverrides),
3247
- chartTextOverrides: cloneSerializable(chartTextOverrides),
3248
- chartTypeOverrides: cloneSerializable(chartTypeOverrides),
3249
- deletedReportBlockIds: [...deletedReportBlockIds],
3250
- pageTitle,
3251
- tableColumnWidths: cloneSerializable(tableColumnWidths),
3252
- tableTextOverrides: cloneSerializable(tableTextOverrides)
3253
- };
3254
- layoutDraftsRef.current = { dashboard: null, report: null };
3255
- closeInlineMenus();
3256
- setIsEditMode(true);
3257
- }
3258
- function cancelEditMode() {
3259
- const snapshotState = editSnapshotRef.current;
3260
- if (snapshotState) {
3261
- setBlockTextOverrides(cloneSerializable(snapshotState.blockTextOverrides));
3262
- setChartSpecOverrides(cloneSerializable(snapshotState.chartSpecOverrides ?? {}));
3263
- setChartTextOverrides(cloneSerializable(snapshotState.chartTextOverrides));
3264
- setChartTypeOverrides(cloneSerializable(snapshotState.chartTypeOverrides));
3265
- setDeletedReportBlockIds([...snapshotState.deletedReportBlockIds]);
3266
- setPageTitle(snapshotState.pageTitle);
3267
- setTableColumnWidths(cloneSerializable(snapshotState.tableColumnWidths));
3268
- setTableTextOverrides(cloneSerializable(snapshotState.tableTextOverrides));
3269
- }
3270
- editSnapshotRef.current = null;
3271
- layoutDraftsRef.current = { dashboard: null, report: null };
3272
- closeInlineMenus();
3273
- setIsEditMode(false);
3274
- setLayoutResetKey((current) => current + 1);
3275
- }
3276
- function saveEditMode() {
3277
- persistEditableState();
3278
- editSnapshotRef.current = null;
3279
- layoutDraftsRef.current = { dashboard: null, report: null };
3280
- closeInlineMenus();
3281
- setIsEditMode(false);
3282
- }
3283
- function recordDashboardLayoutDraft(nextItems) {
3284
- layoutDraftsRef.current.dashboard = nextItems;
3285
- }
3286
- function recordReportLayoutDraft(nextItems) {
3287
- layoutDraftsRef.current.report = nextItems;
3288
- }
3289
- function updatePageTitle(nextTitle) {
3290
- setPageTitle(nextTitle);
3291
- if (!isEditMode && pageTitleTextStorageKey) {
3292
- window.localStorage.setItem(pageTitleTextStorageKey, nextTitle);
3293
- }
3294
- }
3295
- function updateChartText(chartId, nextText) {
3296
- setChartTextOverrides((current) => {
3297
- const merged = {
3298
- ...current,
3299
- [chartId]: {
3300
- ...current[chartId],
3301
- ...nextText
3302
- }
3303
- };
3304
- if (!isEditMode && chartTextStorageKey) {
3305
- window.localStorage.setItem(chartTextStorageKey, JSON.stringify(merged));
3306
- }
3307
- return merged;
3308
- });
3309
- }
3310
- function updateChartType(chartId, nextType) {
3311
- setChartTypeOverrides((current) => {
3312
- const originalType = charts.find((chart) => chart.id === chartId)?.type;
3313
- const merged = { ...current };
3314
- if (!originalType || nextType === originalType) {
3315
- delete merged[chartId];
3316
- }
3317
- else {
3318
- merged[chartId] = nextType;
3319
- }
3320
- if (!isEditMode && chartTypeStorageKey) {
3321
- window.localStorage.setItem(chartTypeStorageKey, JSON.stringify(merged));
3322
- }
3323
- return merged;
3324
- });
3325
- }
3326
- function updateChartSpec(chartId, widgetSpec) {
3327
- const chart = charts.find((candidate) => candidate.id === chartId);
3328
- if (!chart)
3329
- return;
3330
- if (!widgetSpec) {
3331
- setChartSpecOverrides((current) => {
3332
- const merged = { ...current };
3333
- delete merged[chartId];
3334
- if (!isEditMode && chartSpecStorageKey) {
3335
- window.localStorage.setItem(chartSpecStorageKey, JSON.stringify(merged));
3336
- }
3337
- return merged;
3338
- });
3339
- setChartTypeOverrides((current) => {
3340
- const merged = { ...current };
3341
- delete merged[chartId];
3342
- if (!isEditMode && chartTypeStorageKey) {
3343
- window.localStorage.setItem(chartTypeStorageKey, JSON.stringify(merged));
3344
- }
3345
- return merged;
3346
- });
3347
- return;
3348
- }
3349
- const nextOverride = chartSpecOverrideFromWidgetSpec(chart, widgetSpec);
3350
- const nextType = sharedIsChartType(nextOverride.type) ? nextOverride.type : chart.type;
3351
- setChartSpecOverrides((current) => {
3352
- const merged = { ...current };
3353
- if (Object.keys(nextOverride).length) {
3354
- merged[chartId] = nextOverride;
3355
- }
3356
- else {
3357
- delete merged[chartId];
3358
- }
3359
- if (!isEditMode && chartSpecStorageKey) {
3360
- window.localStorage.setItem(chartSpecStorageKey, JSON.stringify(merged));
3361
- }
3362
- return merged;
3363
- });
3364
- setChartTypeOverrides((current) => {
3365
- const merged = { ...current };
3366
- if (nextType === chart.type) {
3367
- delete merged[chartId];
3368
- }
3369
- else {
3370
- merged[chartId] = nextType;
3371
- }
3372
- if (!isEditMode && chartTypeStorageKey) {
3373
- window.localStorage.setItem(chartTypeStorageKey, JSON.stringify(merged));
3374
- }
3375
- return merged;
3376
- });
3377
- }
3378
- function updateTableColumnWidths(tableId, nextWidths, options = {}) {
3379
- setTableColumnWidths((current) => {
3380
- const tableSpec = tablesById.get(tableId);
3381
- if (!tableSpec)
3382
- return current;
3383
- const validFields = new Set(tableSpec.columns.map((column) => column.field));
3384
- const sanitizedWidths = {};
3385
- for (const [field, rawWidth] of Object.entries(nextWidths)) {
3386
- const width = typeof rawWidth === "number" ? rawWidth : Number(rawWidth);
3387
- if (validFields.has(field) && Number.isFinite(width)) {
3388
- sanitizedWidths[field] = clamp(Math.round(width), TABLE_COLUMN_MIN_WIDTH, TABLE_COLUMN_MAX_WIDTH);
3389
- }
3390
- }
3391
- const merged = { ...current };
3392
- if (Object.keys(sanitizedWidths).length) {
3393
- merged[tableId] = sanitizedWidths;
3394
- }
3395
- else {
3396
- delete merged[tableId];
3397
- }
3398
- if (!isEditMode && options.persist !== false && tableColumnWidthStorageKey) {
3399
- window.localStorage.setItem(tableColumnWidthStorageKey, JSON.stringify(merged));
3400
- }
3401
- return merged;
3402
- });
3403
- }
3404
- function updateTableText(tableId, nextText) {
3405
- setTableTextOverrides((current) => {
3406
- const merged = {
3407
- ...current,
3408
- [tableId]: {
3409
- ...current[tableId],
3410
- ...nextText
3411
- }
3412
- };
3413
- if (!isEditMode && tableTextStorageKey) {
3414
- window.localStorage.setItem(tableTextStorageKey, JSON.stringify(merged));
3415
- }
3416
- return merged;
3417
- });
3418
- }
3419
- function updateBlockText(blockId, nextText) {
3420
- setBlockTextOverrides((current) => {
3421
- const nextBlockOverride = {
3422
- ...current[blockId],
3423
- ...nextText
3424
- };
3425
- if ("bodyMarkdown" in nextText && !visibleString(nextText.bodyMarkdown)) {
3426
- delete nextBlockOverride.bodyMarkdown;
3427
- }
3428
- if ("html" in nextText && !visibleString(nextText.html)) {
3429
- delete nextBlockOverride.html;
3430
- }
3431
- const merged = { ...current };
3432
- if (Object.keys(nextBlockOverride).length)
3433
- merged[blockId] = nextBlockOverride;
3434
- else
3435
- delete merged[blockId];
3436
- if (!isEditMode && blockTextStorageKey) {
3437
- window.localStorage.setItem(blockTextStorageKey, JSON.stringify(merged));
3438
- }
3439
- return merged;
3440
- });
3441
- }
3442
- function deleteReportBlocks(blockIds) {
3443
- const idsToDelete = [...new Set(blockIds)];
3444
- if (!idsToDelete.length)
3445
- return;
3446
- setDeletedReportBlockIds((current) => {
3447
- const existingIds = new Set(current);
3448
- const nextIds = [...current];
3449
- for (const blockId of idsToDelete) {
3450
- if (!existingIds.has(blockId)) {
3451
- nextIds.push(blockId);
3452
- }
3453
- }
3454
- if (nextIds.length === current.length)
3455
- return current;
3456
- if (!isEditMode && deletedReportBlockStorageKey) {
3457
- window.localStorage.setItem(deletedReportBlockStorageKey, JSON.stringify(nextIds));
3458
- }
3459
- return nextIds;
3460
- });
3461
- setOpenMenuBlockId(null);
3462
- setOpenMenuChartId(null);
3463
- setOpenMenuTableId(null);
3464
- }
3465
- function deleteReportBlock(blockId) {
3466
- deleteReportBlocks([blockId]);
3467
- }
3468
- const dashboardContentBlocks = useMemo(() => {
3469
- const chartBlocks = charts.map((chart) => ({
3470
- className: "analytics-layout-item-chart",
3471
- defaultLayout: dashboardCardLayout(chart.layout),
3472
- id: `chart:${chart.id}`,
3473
- render: (layout, { setLayout }) => {
3474
- const overriddenChart = applyChartSpecOverride(chart, chartSpecOverrides[chart.id]);
3475
- const chartRows = filterRowsForDataset(getRows(snapshot, overriddenChart.dataset), overriddenChart.dataset, activeSurfaceFilters, selectedFilters, chartUsedFields(overriddenChart));
3476
- const chartTypeOptions = compatibleChartTypesForArtifactCard(overriddenChart, chartRows);
3477
- const requestedType = chartTypeOverrides[chart.id] ?? overriddenChart.type;
3478
- const activeType = chartTypeOptions.some((option) => option.type === requestedType)
3479
- ? requestedType
3480
- : overriddenChart.type;
3481
- const displayChart = withChartType(overriddenChart, activeType);
3482
- const accessIssue = accessIssueForChart(displayChart, accessIssues);
3483
- return (<VizCard accessIssue={accessIssue} chart={displayChart} chartTypeOptions={chartTypeOptions} isEditMode={activeEditMode} isMenuOpen={openMenuChartId === chart.id} layout={layout} onChartTypeChange={updateChartType} onCopyResult={(message, isError = false) => setCopyMessage({ isError, message })} onRequestEditMode={requestEditMode} onTextChange={updateChartText} onMenuOpenChange={(nextOpen) => {
3484
- setOpenMenuTableId(null);
3485
- setOpenMenuChartId(nextOpen ? chart.id : null);
3486
- }} onModalOpen={setChartModal} textOverride={chartTextOverrides[chart.id]}>
3487
- <ChartBody accessIssue={accessIssue} chart={displayChart} filters={activeSurfaceFilters} layout={layout} selectedFilters={selectedFilters} snapshot={snapshot}/>
3488
- </VizCard>);
3489
- }
3490
- }));
3491
- const tableBlocks = tables.map((table) => ({
3492
- className: "analytics-layout-item-table",
3493
- defaultLayout: dashboardCardLayout(table.layout ?? "full"),
3494
- id: `table:${table.id}`,
3495
- render: (layout) => (<DataTable columnWidths={tableColumnWidths[table.id] ?? {}} filters={activeSurfaceFilters} isEditMode={activeEditMode} isMenuOpen={openMenuTableId === table.id} layout={layout} manifest={manifest} onColumnWidthsChange={updateTableColumnWidths} onMenuOpenChange={(nextOpen) => {
3496
- setOpenMenuChartId(null);
3497
- setOpenMenuTableId(nextOpen ? table.id : null);
3498
- }} onModalOpen={setTableModal} onRequestEditMode={requestEditMode} onTextChange={updateTableText} selectedFilters={selectedFilters} snapshot={snapshot} table={table} textOverride={tableTextOverrides[table.id]}/>)
3499
- }));
3500
- const htmlBlocks = visibleReportGridBlocks
3501
- .filter((block) => block.type === "html")
3502
- .map((block) => ({
3503
- className: "analytics-layout-item-html",
3504
- defaultLayout: dashboardCardLayout(block.layout ?? "full"),
3505
- id: `html:${block.id}`,
3506
- render: () => (<ReportHtmlBlock block={block} htmlOverride={blockTextOverrides[block.id]} isEditMode={activeEditMode} isMenuOpen={openMenuBlockId === block.id} onHtmlChange={updateBlockText} onCopyResult={(message, isError = false) => setCopyMessage({ isError, message })} onDeleteBlock={capabilities.canEdit ? () => deleteReportBlock(block.id) : undefined} onMenuOpenChange={(nextOpen) => {
3507
- setOpenMenuChartId(null);
3508
- setOpenMenuTableId(null);
3509
- setOpenMenuBlockId(nextOpen ? block.id : null);
3510
- }}/>)
3511
- }));
3512
- return [...chartBlocks, ...tableBlocks, ...htmlBlocks];
3513
- }, [
3514
- accessIssues,
3515
- activeSurfaceFilters,
3516
- activeEditMode,
3517
- capabilities.canEdit,
3518
- chartTextOverrides,
3519
- chartSpecOverrides,
3520
- chartTypeOverrides,
3521
- charts,
3522
- manifest,
3523
- openMenuBlockId,
3524
- openMenuChartId,
3525
- openMenuTableId,
3526
- requestEditMode,
3527
- selectedFilters,
3528
- snapshot,
3529
- tableColumnWidths,
3530
- tableTextOverrides,
3531
- tables,
3532
- visibleReportGridBlocks
3533
- ]);
3534
- const reportContentBlocks = useMemo(() => {
3535
- return visibleReportGridBlocks.map((block) => {
3536
- if (block.type === "metric-strip") {
3537
- const metricCards = (block.cardIds ?? [])
3538
- .map((cardId) => cardsById.get(cardId))
3539
- .filter((card) => Boolean(card));
3540
- return {
3541
- className: "report-stack-item report-stack-item-metric-strip",
3542
- defaultLayout: reportCardLayout(block.layout),
3543
- id: block.id,
3544
- render: () => (<ReportMetricStripBlock cards={metricCards} filters={activeSurfaceFilters} id={block.id} isMenuOpen={openMenuBlockId === block.id} onCopyResult={(message, isError = false) => setCopyMessage({ isError, message })} onDeleteBlock={capabilities.canEdit ? () => deleteReportBlock(block.id) : undefined} onMenuOpenChange={(nextOpen) => {
3545
- setOpenMenuChartId(null);
3546
- setOpenMenuTableId(null);
3547
- setOpenMenuBlockId(nextOpen ? block.id : null);
3548
- }} selectedFilters={selectedFilters} snapshot={snapshot}/>)
3549
- };
3550
- }
3551
- const chart = block.chartId ? chartsById.get(block.chartId) : undefined;
3552
- const table = block.tableId ? tablesById.get(block.tableId) : undefined;
3553
- return {
3554
- className: `report-stack-item report-stack-item-${block.type}`,
3555
- defaultLayout: reportCardLayout(block.layout),
3556
- id: block.id,
3557
- render: (layout) => (<ReportBlockCard accessIssues={accessIssues} block={block} blockTextOverride={blockTextOverrides[block.id]} chart={chart} chartSpecOverride={chart ? chartSpecOverrides[chart.id] : undefined} chartTextOverride={chart ? chartTextOverrides[chart.id] : undefined} chartTypeOverride={chart ? chartTypeOverrides[chart.id] : undefined} columnWidths={table ? tableColumnWidths[table.id] ?? {} : {}} filters={activeSurfaceFilters} isBlockMenuOpen={openMenuBlockId === block.id} isChartMenuOpen={Boolean(chart && openMenuChartId === chart.id)} isEditMode={activeEditMode} isTableMenuOpen={Boolean(table && openMenuTableId === table.id)} layout={layout} manifest={manifest} onBlockMenuOpenChange={(nextOpen) => {
3558
- setOpenMenuChartId(null);
3559
- setOpenMenuTableId(null);
3560
- setOpenMenuBlockId(nextOpen ? block.id : null);
3561
- }} onBlockTextChange={updateBlockText} onChartTypeChange={updateChartType} onChartMenuOpenChange={(nextOpen) => {
3562
- setOpenMenuTableId(null);
3563
- setOpenMenuBlockId(null);
3564
- setOpenMenuChartId(chart && nextOpen ? chart.id : null);
3565
- }} onChartModalOpen={setChartModal} onColumnWidthsChange={updateTableColumnWidths} onCopyResult={(message, isError = false) => setCopyMessage({ isError, message })} onDeleteBlock={capabilities.canEdit ? () => deleteReportBlock(block.id) : undefined} onRequestEditMode={requestEditMode} onTableMenuOpenChange={(nextOpen) => {
3566
- setOpenMenuChartId(null);
3567
- setOpenMenuBlockId(null);
3568
- setOpenMenuTableId(table && nextOpen ? table.id : null);
3569
- }} onTableModalOpen={setTableModal} onTableTextChange={updateTableText} onTextChange={updateChartText} selectedFilters={selectedFilters} snapshot={snapshot} table={table} tableTextOverride={table ? tableTextOverrides[table.id] : undefined}/>)
3570
- };
3571
- });
3572
- }, [
3573
- accessIssues,
3574
- activeSurfaceFilters,
3575
- activeEditMode,
3576
- blockTextOverrides,
3577
- cardsById,
3578
- capabilities.canEdit,
3579
- chartSpecOverrides,
3580
- chartTextOverrides,
3581
- chartTypeOverrides,
3582
- chartsById,
3583
- manifest,
3584
- openMenuBlockId,
3585
- openMenuChartId,
3586
- openMenuTableId,
3587
- requestEditMode,
3588
- selectedFilters,
3589
- snapshot,
3590
- tableColumnWidths,
3591
- tableTextOverrides,
3592
- tablesById,
3593
- visibleReportGridBlocks
3594
- ]);
3595
- if (error) {
3596
- return (<DashboardShell surface={manifest?.surface}>
3597
- <div className="empty-state error-state">{error}</div>
3598
- </DashboardShell>);
3599
- }
3600
- const activeFilters = activeFilterSummary(activeSurfaceFilters, selectedFilters);
3601
- const chartModalSourceChart = chartModal
3602
- ? chartsById.get(chartModal.chart.id) ?? chartModal.chart
3603
- : null;
3604
- const chartModalBaseChart = chartModalSourceChart
3605
- ? applyChartSpecOverride(chartModalSourceChart, chartSpecOverrides[chartModalSourceChart.id])
3606
- : null;
3607
- const chartModalRows = chartModalBaseChart
3608
- ? filterRowsForDataset(getRows(snapshot, chartModalBaseChart.dataset), chartModalBaseChart.dataset, activeSurfaceFilters, selectedFilters, chartUsedFields(chartModalBaseChart))
3609
- : [];
3610
- const chartModalTypeOptions = chartModalBaseChart
3611
- ? compatibleChartTypesFor(chartModalBaseChart, chartModalRows)
3612
- : [];
3613
- const chartModalRequestedType = chartModalBaseChart
3614
- ? chartTypeOverrides[chartModalBaseChart.id] ?? chartModalBaseChart.type
3615
- : null;
3616
- const chartModalActiveType = chartModalRequestedType && chartModalTypeOptions.some((option) => option.type === chartModalRequestedType)
3617
- ? chartModalRequestedType
3618
- : chartModalBaseChart?.type ?? null;
3619
- const activeChartModal = chartModal?.kind === "fullscreen" && chartModalBaseChart && chartModalActiveType
3620
- ? {
3621
- chart: withChartType({
3622
- ...chartModalBaseChart,
3623
- subtitle: chartModal.chart.subtitle,
3624
- title: chartModal.chart.title
3625
- }, chartModalActiveType)
3626
- }
3627
- : null;
3628
- if (isReport) {
3629
- return (<DashboardShell isEditMode={activeEditMode} surface="report">
3630
- <AnalyticsTopBar chrome={displayMode === "inline" ? "inline" : "full"} isEditMode={activeEditMode} manifest={manifest} onCancelEdit={cancelEditMode} onCopyResult={(message, isError = false) => setCopyMessage({ isError, message })} onEdit={requestEditMode} onRequestFullscreen={onRequestFullscreen} onSaveEdit={saveEditMode} onTitleChange={updatePageTitle} packageInfo={packageInfo} snapshot={snapshot} title={pageTitle}/>
3631
- <AccessIssueStrip issues={accessIssues}/>
3632
- {copyMessage ? (<div className={`copy-toast ${copyMessage.isError ? "error" : ""}`} role="status">
3633
- {copyMessage.message}
3634
- </div>) : null}
3635
-
3636
- <AnalyticsLayoutCanvas ariaLabel="Report blocks" blocks={reportContentBlocks} cancelSelector={CARD_DRAG_CANCEL_SELECTOR} className="report-content-grid report-block-stack" isEditMode={activeEditMode} layoutResetKey={layoutResetKey} onLayoutChange={recordReportLayoutDraft} storageKey={reportStorageKey}/>
3637
- {activeChartModal ? (<ChartDetailPage accessIssue={accessIssueForChart(activeChartModal.chart, accessIssues)} chart={activeChartModal.chart} filters={activeSurfaceFilters} manifest={manifest} onChartSpecChange={updateChartSpec} onClose={() => setChartModal(null)} packageInfo={packageInfo} rows={chartModalRows} selectedFilters={selectedFilters} snapshot={snapshot}/>) : null}
3638
- {chartModal?.kind === "source" && chartModalBaseChart ? (<ChartSourceModalDialog activeFilters={activeFilters} chart={{
3639
- ...chartModalBaseChart,
3640
- subtitle: chartModal.chart.subtitle,
3641
- title: chartModal.chart.title
3642
- }} manifest={manifest} onClose={() => setChartModal(null)} rows={chartModalRows} snapshot={snapshot}/>) : null}
3643
- {tableModal ? (<TableModalDialog activeFilters={activeFilters} columnWidths={tableColumnWidths[tableModal.table.id] ?? {}} filters={activeSurfaceFilters} kind={tableModal.kind} manifest={manifest} onColumnWidthsChange={updateTableColumnWidths} onClose={() => setTableModal(null)} selectedFilters={selectedFilters} snapshot={snapshot} table={tableModal.table}/>) : null}
3644
- </DashboardShell>);
3645
- }
3646
- return (<DashboardShell isEditMode={activeEditMode} surface={manifest?.surface}>
3647
- <AnalyticsTopBar chrome={displayMode === "inline" ? "inline" : "full"} isEditMode={activeEditMode} manifest={manifest} onCancelEdit={cancelEditMode} onCopyResult={(message, isError = false) => setCopyMessage({ isError, message })} onEdit={requestEditMode} onRequestFullscreen={onRequestFullscreen} onSaveEdit={saveEditMode} onTitleChange={updatePageTitle} packageInfo={packageInfo} snapshot={snapshot} title={pageTitle}/>
3648
- <AccessIssueStrip issues={accessIssues}/>
3649
- {copyMessage ? (<div className={`copy-toast ${copyMessage.isError ? "error" : ""}`} role="status">
3650
- {copyMessage.message}
3651
- </div>) : null}
3652
-
3653
- <FilterToolbar filters={activeSurfaceFilters} onChange={setSelectedFilters} selectedFilters={selectedFilters} snapshot={snapshot}/>
3654
-
3655
- <KpiStrip cards={cards} filters={activeSurfaceFilters} selectedFilters={selectedFilters} snapshot={snapshot}/>
3656
-
3657
- <AnalyticsLayoutCanvas ariaLabel="Dashboard content" blocks={dashboardContentBlocks} cancelSelector={CARD_DRAG_CANCEL_SELECTOR} className="dashboard-content-grid" isEditMode={activeEditMode} layoutResetKey={layoutResetKey} onLayoutChange={recordDashboardLayoutDraft} storageKey={storageKey}/>
3658
- {activeChartModal ? (<ChartDetailPage accessIssue={accessIssueForChart(activeChartModal.chart, accessIssues)} chart={activeChartModal.chart} filters={activeSurfaceFilters} manifest={manifest} onChartSpecChange={updateChartSpec} onClose={() => setChartModal(null)} packageInfo={packageInfo} rows={chartModalRows} selectedFilters={selectedFilters} snapshot={snapshot}/>) : null}
3659
- {chartModal?.kind === "source" && chartModalBaseChart ? (<ChartSourceModalDialog activeFilters={activeFilters} chart={{
3660
- ...chartModalBaseChart,
3661
- subtitle: chartModal.chart.subtitle,
3662
- title: chartModal.chart.title
3663
- }} manifest={manifest} onClose={() => setChartModal(null)} rows={chartModalRows} snapshot={snapshot}/>) : null}
3664
- {tableModal ? (<TableModalDialog activeFilters={activeFilters} columnWidths={tableColumnWidths[tableModal.table.id] ?? {}} filters={activeSurfaceFilters} kind={tableModal.kind} manifest={manifest} onColumnWidthsChange={updateTableColumnWidths} onClose={() => setTableModal(null)} selectedFilters={selectedFilters} snapshot={snapshot} table={tableModal.table}/>) : null}
3665
- </DashboardShell>);
3666
- }