openyida 2026.9.21 → 2026.9.22-beta.2

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 (334) hide show
  1. package/README.md +14 -20
  2. package/bin/yida.js +6 -11
  3. package/lib/app/app-list.js +3 -7
  4. package/lib/app/canvas-compile.js +12 -22
  5. package/lib/app/check-prd-completeness.js +0 -7
  6. package/lib/app/create-app.js +1 -4
  7. package/lib/app/create-form/args.js +12 -37
  8. package/lib/app/create-form/batch.js +11 -86
  9. package/lib/app/create-form.js +86 -193
  10. package/lib/app/create-page.js +17 -84
  11. package/lib/app/custom-theme.js +0 -11
  12. package/lib/app/form-field-validator.js +41 -26
  13. package/lib/app/form-open-guard.js +10 -97
  14. package/lib/app/get-form-config.js +0 -1
  15. package/lib/app/inline-css-guard.js +31 -1
  16. package/lib/app/services/form-compiler.js +4 -2
  17. package/lib/app/theme-from-design.js +41 -144
  18. package/lib/app/theme-presets.js +1 -1
  19. package/lib/app/update-app.js +13 -63
  20. package/lib/asset/ai-image.js +9 -59
  21. package/lib/asset/asset-cmd.js +7 -18
  22. package/lib/asset/asset-plan.js +9 -102
  23. package/lib/asset/asset-resolve.js +10 -55
  24. package/lib/asset/asset-status.js +4 -5
  25. package/lib/asset/host-capabilities.js +2 -11
  26. package/lib/asset/url-verify.js +4 -19
  27. package/lib/auth/dws-sync.js +148 -0
  28. package/lib/auth/token-auth.js +73 -9
  29. package/lib/auth/token-store.js +50 -0
  30. package/lib/connector/connector-test.js +5 -19
  31. package/lib/connector/contract.js +1 -3
  32. package/lib/core/agent-capabilities.js +16 -19
  33. package/lib/core/command-manifest.js +40 -329
  34. package/lib/core/locales/en.js +17 -74
  35. package/lib/core/locales/zh.js +16 -73
  36. package/lib/core/redact.js +10 -15
  37. package/lib/core/sample.js +30 -72
  38. package/lib/core/utils.js +4 -0
  39. package/lib/design-plan/design-plan.js +4 -51
  40. package/lib/design-plan/init.js +26 -121
  41. package/lib/design-plan/materialize.js +348 -451
  42. package/lib/design-plan/normalize.js +29 -74
  43. package/lib/design-plan/parallel.js +16 -71
  44. package/lib/design-plan/patch.js +16 -63
  45. package/lib/design-plan/preview.js +8 -6
  46. package/lib/design-plan/validate.js +11 -71
  47. package/lib/process/create-process.js +50 -84
  48. package/lib/samples/openyida-scaffold/canvas-form-drawer.canvas.jsx +90 -20
  49. package/lib/samples/openyida-scaffold/canvas-nav/content.jsx +13 -93
  50. package/lib/samples/openyida-scaffold/canvas-nav/data.jsx +18 -100
  51. package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +4 -6
  52. package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +5 -5
  53. package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +2 -1
  54. package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +1 -1
  55. package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +9 -15
  56. package/lib/samples/yida-canvas-table-form/table-form-batch-submit.canvas.jsx +83 -9
  57. package/lib/samples/yida-rechart/trend-combo.canvas.jsx +87 -14
  58. package/package.json +1 -3
  59. package/scripts/postinstall.js +3 -3
  60. package/yida-skills/SKILL.md +16 -19
  61. package/yida-skills/references/official-example-schema-patterns.md +1 -1
  62. package/yida-skills/references/yida-api.md +0 -4
  63. package/yida-skills/skills/yida-app/SKILL.md +23 -46
  64. package/yida-skills/skills/yida-app/workflow/parallel-work.md +6 -15
  65. package/yida-skills/skills/yida-app/workflow/plan/step-1-understand.md +1 -1
  66. package/yida-skills/skills/yida-app/workflow/plan/step-2-confirm.md +1 -1
  67. package/yida-skills/skills/yida-app/workflow/plan/step-4-deliver.md +15 -29
  68. package/yida-skills/skills/yida-app/workflow/plan/workflow.md +11 -29
  69. package/yida-skills/skills/yida-app/workflow/step-1-resource-context.md +2 -4
  70. package/yida-skills/skills/yida-app/workflow/step-2-design.md +9 -23
  71. package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +4 -6
  72. package/yida-skills/skills/yida-app/workflow/step-4-forms-processes.md +4 -15
  73. package/yida-skills/skills/yida-app/workflow/step-6-main-page.md +4 -6
  74. package/yida-skills/skills/yida-app/workflow/step-7-page-code.md +9 -15
  75. package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +11 -25
  76. package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +28 -68
  77. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +43 -42
  78. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-style-implementation-guide.md +44 -60
  79. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-theme-provider.md +50 -72
  80. package/yida-skills/skills/yida-canvas-custom-page/references/component-library-guide.md +1 -13
  81. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +1 -140
  82. package/yida-skills/skills/yida-canvas-custom-page/references/navigation-and-entry-guide.md +72 -101
  83. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +32 -35
  84. package/yida-skills/skills/yida-canvas-custom-page/scripts/build-canvas-theme.js +3 -29
  85. package/yida-skills/skills/yida-canvas-custom-page/scripts/canvas-theme-provider.template.jsx +6 -69
  86. package/yida-skills/skills/yida-canvas-data-binding/SKILL.md +0 -26
  87. package/yida-skills/skills/yida-create-app/SKILL.md +0 -2
  88. package/yida-skills/skills/yida-create-form-page/SKILL.md +58 -72
  89. package/yida-skills/skills/yida-create-form-page/references/advanced-form-modes.md +5 -5
  90. package/yida-skills/skills/yida-create-form-page/references/association-form-field.md +4 -4
  91. package/yida-skills/skills/yida-create-form-page/references/batch-forms.md +5 -6
  92. package/yida-skills/skills/yida-create-form-page/references/field-definition-guide.md +19 -7
  93. package/yida-skills/skills/yida-create-form-page/references/form-field-properties.md +44 -62
  94. package/yida-skills/skills/yida-create-page/SKILL.md +6 -14
  95. package/yida-skills/skills/yida-create-process/SKILL.md +2 -13
  96. package/yida-skills/skills/yida-custom-page/SKILL.md +0 -2
  97. package/yida-skills/skills/yida-custom-page/references/design-system.md +1 -1
  98. package/yida-skills/skills/yida-dashboard/SKILL.md +4 -5
  99. package/yida-skills/skills/yida-data-management/SKILL.md +2 -4
  100. package/yida-skills/skills/yida-data-management/references/data-format-guide.md +4 -4
  101. package/yida-skills/skills/yida-design/SKILL.md +14 -29
  102. package/yida-skills/skills/yida-design/references/app/blueprint.md +70 -0
  103. package/yida-skills/skills/yida-design/references/app/navigation-patterns.md +43 -0
  104. package/yida-skills/skills/yida-design/references/app/role-journey.md +30 -0
  105. package/yida-skills/skills/yida-design/references/ask-human-interaction-contract.md +42 -67
  106. package/yida-skills/skills/yida-design/references/asset-workflow.md +2 -6
  107. package/yida-skills/skills/yida-design/references/design-mode.md +4 -4
  108. package/yida-skills/skills/yida-design/references/page-quality-gates.md +38 -26
  109. package/yida-skills/skills/yida-design/references/style-design-selection.md +137 -0
  110. package/yida-skills/skills/yida-design/references/style-designs/_design-md-template.md +185 -0
  111. package/yida-skills/skills/yida-design/references/style-designs/aqua-service-progress-dashboard.md +242 -0
  112. package/yida-skills/skills/yida-design/references/style-designs/blue-insight-operations-dashboard.md +243 -0
  113. package/yida-skills/skills/yida-design/references/style-designs/blue-productivity-insight-workbench.md +242 -0
  114. package/yida-skills/skills/yida-design/references/style-designs/command-filter-card-console.md +304 -0
  115. package/yida-skills/skills/yida-design/references/style-designs/contrast-command-analytics-workbench.md +261 -0
  116. package/yida-skills/skills/yida-design/references/style-designs/dark-stage-analytic-dashboard.md +369 -0
  117. package/yida-skills/skills/yida-design/references/style-designs/filterable-card-catalog.md +354 -0
  118. package/yida-skills/skills/yida-design/references/style-designs/green-timeline-progress-workbench.md +250 -0
  119. package/yida-skills/skills/yida-design/references/style-designs/registry.md +117 -0
  120. package/yida-skills/skills/yida-design/references/style-designs/soft-analytic-workbench.md +348 -0
  121. package/yida-skills/skills/yida-design/references/style-designs/soft-blue-grid-analytic-dashboard.md +658 -0
  122. package/yida-skills/skills/yida-design/references/style-designs/soft-bordered-analytic-workbench.md +385 -0
  123. package/yida-skills/skills/yida-design/references/style-designs/soft-curated-filter-gallery.md +300 -0
  124. package/yida-skills/skills/yida-design/references/style-designs/soft-modular-analytic-workbench.md +404 -0
  125. package/yida-skills/skills/yida-design/references/style-designs/soft-progress-analytics-workbench.md +382 -0
  126. package/yida-skills/skills/yida-design/references/style-designs/soft-timeline-analytics-workbench.md +367 -0
  127. package/yida-skills/skills/yida-design/references/style-designs/teal-rail-analytics-workbench.md +341 -0
  128. package/yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css +432 -350
  129. package/yida-skills/skills/yida-design/references/visual-decision-engine.md +143 -19
  130. package/yida-skills/skills/yida-design/references/visual-scaffold-recipes.md +27 -15
  131. package/yida-skills/skills/yida-design/sub_skill/page-design/SKILL.md +0 -4
  132. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +8 -22
  133. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/README.md +10 -14
  134. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/build-plan-template.html +4 -9
  135. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +27 -49
  136. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-schema.md +154 -33
  137. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-design.md +127 -48
  138. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-theme-selection.md +51 -37
  139. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/render_build_plan.py +48 -43
  140. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/validate_design_themes.py +190 -0
  141. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/README.md +98 -0
  142. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-media-grid.md +339 -0
  143. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-modular-clarity.md +348 -0
  144. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-structured-clarity.md +344 -0
  145. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ambient-halo-layered.md +345 -0
  146. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-focus-layered.md +355 -0
  147. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-luminous-modular.md +377 -0
  148. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/deep-stage-duotone.md +352 -0
  149. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/hairline-runway-clarity.md +389 -0
  150. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/high-contrast-modular.md +364 -0
  151. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/index.json +329 -0
  152. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/interlocked-vivid-modules.md +348 -0
  153. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/matrix-grid-focus.md +345 -0
  154. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/media-rail-inspector.md +379 -0
  155. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mist-layered-signal.md +347 -0
  156. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/modular-rail-signal.md +352 -0
  157. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mono-grid-signal.md +386 -0
  158. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ribbon-ledger-lift.md +384 -0
  159. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/segmented-meter-clarity.md +388 -0
  160. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/split-rail-precision.md +341 -0
  161. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/status-framed-media-grid.md +361 -0
  162. package/yida-skills/skills/yida-design/workflow/output-design.md +375 -117
  163. package/yida-skills/skills/yida-design/workflow/output-prd.md +185 -0
  164. package/yida-skills/skills/yida-design/workflow/step-1-read-brief.md +1 -1
  165. package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +29 -33
  166. package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +1 -3
  167. package/yida-skills/skills/yida-design/workflow/step-5-visual-states.md +106 -22
  168. package/yida-skills/skills/yida-design/workflow/step-6-handoff.md +22 -15
  169. package/yida-skills/skills/yida-form-permission/SKILL.md +0 -6
  170. package/yida-skills/skills/yida-image-assets/SKILL.md +50 -73
  171. package/yida-skills/skills/yida-image-assets/references/manifest-contract.md +52 -82
  172. package/yida-skills/skills/yida-image-assets/references/source-policy.md +15 -14
  173. package/yida-skills/skills/yida-integration/SKILL.md +0 -1
  174. package/yida-skills/skills/yida-login/SKILL.md +0 -2
  175. package/yida-skills/skills/yida-nav-group/SKILL.md +2 -4
  176. package/yida-skills/skills/yida-nav-shell/SKILL.md +12 -36
  177. package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +136 -79
  178. package/yida-skills/skills/yida-page-config/SKILL.md +4 -13
  179. package/yida-skills/skills/yida-prd/SKILL.md +3 -5
  180. package/yida-skills/skills/yida-prd/references/app/blueprint.md +4 -4
  181. package/yida-skills/skills/yida-prd/references/app/navigation-patterns.md +3 -6
  182. package/yida-skills/skills/yida-prd/references/app/role-journey.md +3 -5
  183. package/yida-skills/skills/yida-prd/references/plan-content.md +0 -4
  184. package/yida-skills/skills/yida-prd/workflow/output-prd.md +11 -18
  185. package/yida-skills/skills/yida-prd/workflow/plan-business.md +4 -4
  186. package/yida-skills/skills/yida-prd/workflow/step-2-information-architecture.md +8 -11
  187. package/yida-skills/skills/yida-publish-page/SKILL.md +1 -9
  188. package/yida-skills/skills/yida-requirement-analysis/SKILL.md +39 -10
  189. package/yida-skills/skills/yida-requirement-analysis/workflow/prepare-brief.md +71 -40
  190. package/yida-skills/skills-index.json +16 -36
  191. package/lib/app/application-entry-urls.js +0 -31
  192. package/lib/app/application-style.js +0 -69
  193. package/lib/app/canvas-icon-exports.json +0 -6160
  194. package/lib/app/canvas-icon-guard.js +0 -87
  195. package/lib/app/canvas-navigation-guard.js +0 -84
  196. package/lib/app/canvas-path-guard.js +0 -78
  197. package/lib/app/canvas-theme-guard.js +0 -184
  198. package/lib/app/form-data-response-guard.js +0 -57
  199. package/lib/asset/asset-execution.js +0 -79
  200. package/lib/core/css-structure.js +0 -37
  201. package/lib/design/check-design.js +0 -51
  202. package/lib/design/document.js +0 -458
  203. package/lib/design/icon-contrast.js +0 -85
  204. package/lib/design/page-content.js +0 -11
  205. package/lib/design-plan/artifact-updates.js +0 -117
  206. package/lib/design-plan/confirmation.js +0 -13
  207. package/lib/design-plan/entry-navigation.js +0 -97
  208. package/lib/design-plan/navigation-policy.js +0 -38
  209. package/lib/design-plan/rebase.js +0 -60
  210. package/lib/design-plan/themes.js +0 -101
  211. package/lib/design-plan/visual-policy.js +0 -42
  212. package/lib/samples/openyida-scaffold/canvas-admin-entry.jsx +0 -62
  213. package/lib/samples/openyida-scaffold/canvas-navigation.jsx +0 -56
  214. package/lib/samples/openyida-scaffold/canvas-view-state.jsx +0 -74
  215. package/yida-skills/skills/yida-app/references/entry-navigation.md +0 -193
  216. package/yida-skills/skills/yida-canvas-custom-page/references/view-state-recovery.md +0 -52
  217. package/yida-skills/skills/yida-canvas-data-binding/references/business-action-permissions.md +0 -31
  218. package/yida-skills/skills/yida-design/references/application-style-library.md +0 -93
  219. package/yida-skills/skills/yida-design/references/application-theme-consistency.md +0 -150
  220. package/yida-skills/skills/yida-design/references/native-form-styles.md +0 -208
  221. package/yida-skills/skills/yida-design/references/navigation-decision.md +0 -53
  222. package/yida-skills/skills/yida-design/references/page-continuity.md +0 -42
  223. package/yida-skills/skills/yida-design/references/theme/application-style-recipes.css +0 -58
  224. package/yida-skills/skills/yida-design/references/theme-selection.md +0 -67
  225. package/yida-skills/skills/yida-design/scripts/validate_design_themes.py +0 -302
  226. package/yida-skills/skills/yida-design/templates/application-styles.json +0 -398
  227. package/yida-skills/skills/yida-design/templates/design-themes/README.md +0 -73
  228. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/app_theme.css +0 -748
  229. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/design.md +0 -274
  230. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/form-layout.json +0 -15
  231. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/app_theme.css +0 -748
  232. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/design.md +0 -274
  233. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/form-layout.json +0 -14
  234. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/app_theme.css +0 -748
  235. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/design.md +0 -274
  236. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/form-layout.json +0 -13
  237. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/app_theme.css +0 -748
  238. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/design.md +0 -274
  239. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/form-layout.json +0 -14
  240. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/app_theme.css +0 -748
  241. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/design.md +0 -274
  242. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/form-layout.json +0 -14
  243. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/app_theme.css +0 -748
  244. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/design.md +0 -274
  245. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/form-layout.json +0 -14
  246. package/yida-skills/skills/yida-design/templates/design-themes/app-line/app_theme.css +0 -748
  247. package/yida-skills/skills/yida-design/templates/design-themes/app-line/design.md +0 -274
  248. package/yida-skills/skills/yida-design/templates/design-themes/app-line/form-layout.json +0 -13
  249. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/app_theme.css +0 -748
  250. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/design.md +0 -274
  251. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/form-layout.json +0 -14
  252. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/app_theme.css +0 -754
  253. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/design.md +0 -279
  254. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/form-layout.json +0 -13
  255. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/app_theme.css +0 -748
  256. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/design.md +0 -274
  257. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/form-layout.json +0 -13
  258. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/app_theme.css +0 -748
  259. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/design.md +0 -274
  260. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/form-layout.json +0 -14
  261. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/app_theme.css +0 -748
  262. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/design.md +0 -274
  263. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/form-layout.json +0 -14
  264. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/app_theme.css +0 -758
  265. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/design.md +0 -281
  266. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/form-layout.json +0 -14
  267. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/app_theme.css +0 -748
  268. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/design.md +0 -274
  269. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/form-layout.json +0 -14
  270. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/app_theme.css +0 -748
  271. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/design.md +0 -274
  272. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/form-layout.json +0 -14
  273. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/app_theme.css +0 -754
  274. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/design.md +0 -279
  275. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/form-layout.json +0 -14
  276. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/app_theme.css +0 -752
  277. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/design.md +0 -278
  278. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/form-layout.json +0 -13
  279. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/app_theme.css +0 -748
  280. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/design.md +0 -274
  281. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/form-layout.json +0 -14
  282. package/yida-skills/skills/yida-design/templates/design-themes/basic-tokens.json +0 -118
  283. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/app_theme.css +0 -690
  284. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/design.md +0 -382
  285. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/form-layout.json +0 -13
  286. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css +0 -691
  287. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/design.md +0 -380
  288. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/form-layout.json +0 -13
  289. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/app_theme.css +0 -696
  290. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/design.md +0 -378
  291. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/form-layout.json +0 -13
  292. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/app_theme.css +0 -689
  293. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/design.md +0 -238
  294. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/form-layout.json +0 -13
  295. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/app_theme.css +0 -692
  296. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/design.md +0 -375
  297. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/form-layout.json +0 -13
  298. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/app_theme.css +0 -691
  299. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/design.md +0 -362
  300. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/form-layout.json +0 -13
  301. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/app_theme.css +0 -691
  302. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/design.md +0 -409
  303. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/form-layout.json +0 -13
  304. package/yida-skills/skills/yida-design/templates/design-themes/index.json +0 -464
  305. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/app_theme.css +0 -701
  306. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/design.md +0 -379
  307. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/form-layout.json +0 -13
  308. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/app_theme.css +0 -691
  309. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/design.md +0 -404
  310. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/form-layout.json +0 -13
  311. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/app_theme.css +0 -698
  312. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/design.md +0 -389
  313. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/form-layout.json +0 -13
  314. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/app_theme.css +0 -691
  315. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/design.md +0 -372
  316. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/form-layout.json +0 -13
  317. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/app_theme.css +0 -690
  318. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/design.md +0 -455
  319. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/form-layout.json +0 -13
  320. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/app_theme.css +0 -698
  321. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/design.md +0 -394
  322. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/form-layout.json +0 -13
  323. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/app_theme.css +0 -692
  324. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/design.md +0 -391
  325. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/form-layout.json +0 -13
  326. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/app_theme.css +0 -711
  327. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/design.md +0 -408
  328. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/form-layout.json +0 -13
  329. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/app_theme.css +0 -692
  330. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/design.md +0 -383
  331. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/form-layout.json +0 -13
  332. package/yida-skills/skills/yida-design/templates/navigation-styles.json +0 -769
  333. package/yida-skills/skills/yida-requirement-analysis/references/experience-groups.md +0 -79
  334. package/yida-skills/skills/yida-requirement-analysis/references/handoff.md +0 -68
@@ -1,11 +1,8 @@
1
1
  import React from 'react';
2
2
 
3
- /**
4
- * workspace 保持原有剩余高度布局;document 用于首屏背景与导航共享画布的连续长页。
5
- * document 首屏内容使用 --openyida-navigation-height 留安全区,背景仍从页面顶部开始。
6
- * preserveScroll 只恢复当前实例内本地视图的位置;筛选、数据、草稿和路由由调用方持有。
7
- * 导航节点不随 contentKey 重建;不要给整个壳添加随菜单变化的 key。
8
- */
3
+ // 顶部导航与内容的高度链;侧栏布局可在侧栏右侧已分配高度的区域使用 height="100%"。
4
+ // 只管理布局:菜单权限、URL/hash、离开未保存表单的确认由调用方处理。
5
+ // 合并到页面时保留组件,合并重复 import;不要额外包裹滚动卡片。
9
6
  function CanvasNavigationContent({
10
7
  navigation,
11
8
  children,
@@ -17,99 +14,22 @@ function CanvasNavigationContent({
17
14
  gutter = 'clamp(12px, 2vw, 24px)',
18
15
  radius = 16,
19
16
  background = 'transparent',
20
- layout = 'workspace',
21
- preserveScroll = false,
22
- navigationPosition = 'sticky',
23
- navigationTop = 0,
24
17
  }) {
25
18
  const embedded = Boolean(iframeSrc);
26
- const documentLayout = layout === 'document';
27
- const rootRef = React.useRef(null);
28
- const navigationRef = React.useRef(null);
29
- const contentRef = React.useRef(null);
30
- const scrollPositions = React.useRef(new Map());
31
-
32
- // 测量真实菜单高度,兼容窄屏换行、字体加载和菜单展开,不猜固定的 80px。
33
- React.useLayoutEffect(() => {
34
- if (!documentLayout) return;
35
- const root = rootRef.current;
36
- const nav = navigationRef.current;
37
- if (!root) return;
38
- const navStyle = nav ? { position: nav.style.position, left: nav.style.left, width: nav.style.width, top: nav.style.top } : null;
39
- const measure = () => {
40
- const navHeight = nav?.getBoundingClientRect().height || 0;
41
- root.style.setProperty('--openyida-navigation-height', `${navHeight}px`);
42
- const bounds = root.getBoundingClientRect();
43
- // scroll 事件捕获覆盖宿主内滚动;不假设 window.scrollY 是实际滚动位置。
44
- let boundary = 0;
45
- for (let ancestor = root.parentElement; ancestor; ancestor = ancestor.parentElement) {
46
- if (/(auto|scroll)/.test(window.getComputedStyle(ancestor).overflowY)) {
47
- boundary = ancestor.getBoundingClientRect().top + ancestor.clientTop;
48
- break;
49
- }
50
- }
51
- const top = Math.max(0, boundary) + navigationTop;
52
- root.dataset.scrolled = String(bounds.top < top - 1);
53
- if (nav && navigationPosition === 'fixed') {
54
- // 仅覆盖本页宽度,不能盖住平台侧栏;离开页面底部后随本页退出。
55
- Object.assign(nav.style, { position: 'fixed', left: `${bounds.left}px`, width: `${bounds.width}px`,
56
- top: `${Math.min(Math.max(bounds.top, top), bounds.bottom - navHeight)}px` });
57
- }
58
- };
59
- measure();
60
- const observer = nav && window.ResizeObserver ? new window.ResizeObserver(measure) : null;
61
- if (observer) observer.observe(nav);
62
- if (observer) observer.observe(root);
63
- window.addEventListener('resize', measure);
64
- window.addEventListener('scroll', measure, true);
65
- return () => {
66
- if (observer) observer.disconnect();
67
- window.removeEventListener('resize', measure);
68
- window.removeEventListener('scroll', measure, true);
69
- if (navStyle) Object.assign(nav.style, navStyle);
70
- };
71
- }, [documentLayout, navigation != null, navigationPosition, navigationTop]);
72
-
73
- React.useLayoutEffect(() => {
74
- const viewport = contentRef.current;
75
- if (documentLayout || embedded || !preserveScroll || contentKey == null || !viewport) return;
76
- const position = scrollPositions.current.get(contentKey);
77
- viewport.scrollTop = position?.top || 0;
78
- viewport.scrollLeft = position?.left || 0;
79
- }, [contentKey, documentLayout, embedded, preserveScroll]);
80
-
81
- if (documentLayout && embedded) throw new Error('CanvasNavigationContent: iframeSrc requires workspace layout');
82
- if (!['sticky', 'fixed'].includes(navigationPosition)) throw new Error('CanvasNavigationContent: navigationPosition must be sticky or fixed');
83
19
  return (
84
- <div ref={rootRef} className="openyida-nav-layout" data-layout={layout} data-scrolled="true" style={{
85
- height: documentLayout ? 'auto' : height, minHeight: documentLayout ? 'auto' : 0, minWidth: 0,
86
- display: documentLayout ? 'grid' : 'flex', flexDirection: 'column',
87
- // 长页不创建第二层滚动容器;导航和 main 共享网格区域,背景可到达导航背后。
88
- overflow: documentLayout ? 'visible' : 'hidden', background,
89
- position: 'relative', isolation: 'isolate',
20
+ <div className="openyida-nav-layout" style={{
21
+ height, minHeight: 0, minWidth: 0, display: 'flex', flexDirection: 'column',
22
+ overflow: 'hidden', background,
90
23
  }}>
91
- {navigation != null && <div ref={navigationRef} className="openyida-nav-header" style={{
92
- flexShrink: 0, minWidth: 0, zIndex: 10,
93
- ...(documentLayout ? { gridArea: '1 / 1', alignSelf: 'start', position: 'sticky', top: navigationTop } : {}),
94
- }}>{navigation}</div>}
24
+ {navigation != null && <div style={{ flexShrink: 0 }}>{navigation}</div>}
95
25
  <main className="openyida-nav-main" aria-label={title} style={{
96
- display: documentLayout ? 'block' : 'flex', flexDirection: 'column',
97
- flex: documentLayout ? undefined : '1 1 0', minHeight: documentLayout ? 'auto' : 0,
98
- minWidth: 0, overflow: documentLayout ? 'visible' : 'hidden',
99
- padding: documentLayout ? 0 : gutter, boxSizing: 'border-box',
100
- ...(documentLayout ? { gridArea: '1 / 1' } : {}),
26
+ display: 'flex', flexDirection: 'column', flex: '1 1 0', minHeight: 0,
27
+ minWidth: 0, overflow: 'hidden', padding: gutter, boxSizing: 'border-box',
101
28
  }}>
102
- <div key={contentKey} ref={contentRef} className="openyida-nav-content" onScroll={event => {
103
- // 卸载后 DOM 的 scrollTop 可能已归零,必须在滚动时保存,不能等 effect cleanup。
104
- if (!documentLayout && !embedded && preserveScroll && contentKey != null) {
105
- const viewport = event.currentTarget;
106
- scrollPositions.current.set(contentKey, { top: viewport.scrollTop, left: viewport.scrollLeft });
107
- }
108
- }} style={{
109
- position: 'relative', flex: documentLayout ? undefined : '1 1 0', minHeight: documentLayout ? 'auto' : 0, minWidth: 0,
110
- width: '100%', maxWidth: documentLayout ? undefined : maxWidth,
111
- margin: '0 auto', borderRadius: documentLayout ? 0 : radius,
112
- overflow: documentLayout ? 'visible' : embedded ? 'hidden' : 'auto',
29
+ <div key={contentKey} className="openyida-nav-content" style={{
30
+ position: 'relative', flex: '1 1 0', minHeight: 0, minWidth: 0,
31
+ width: '100%', maxWidth, margin: '0 auto', borderRadius: radius,
32
+ overflow: embedded ? 'hidden' : 'auto',
113
33
  }}>
114
34
  {embedded ? <iframe title={title} src={iframeSrc} style={{
115
35
  position: 'absolute', inset: 0, width: '100%', height: '100%',
@@ -1,131 +1,48 @@
1
- /** local 只切页内视图;platform 沿用平台导航;independent 按真实资源权限过滤。 */
2
- function validateCanvasNavigationItems(items, mode) {
3
- if (!['local', 'platform', 'independent'].includes(mode)) throw new Error('未知导航模式');
4
- for (const item of items) {
5
- if (Array.isArray(item.children) && item.children.length) {
6
- validateCanvasNavigationItems(item.children, mode);
7
- } else if (mode === 'local') {
8
- if (item.targetType !== 'local' || !String(item.key || '').trim() || !String(item.viewKey || '').trim()
9
- || item.href || item.url) throw new Error('local 模式只接受含 key/viewKey 的本页菜单,真实页面请使用 platform 或 independent');
10
- } else if (mode === 'platform' && (item.targetType === 'local' || (!item.formUuid && !item.navUuid))) {
11
- throw new Error('页内菜单不能按平台导航过滤:使用 mode=local 或直接管理本地视图;真实页面需绑定 formUuid/navUuid');
12
- }
13
- }
14
- }
15
-
16
- function filterCanvasNavigation(items, navs, hiddenNav = [], { mode = 'platform', access } = {}) {
17
- validateCanvasNavigationItems(items, mode);
18
- const isHidden = value => value === true || value === 'y' || value === 'true';
1
+ /** PRD 决定菜单结构,平台结果只过滤不可见入口;同一资源可对应多个任务入口。 */
2
+ function filterCanvasNavigation(items, navs, hiddenNav = []) {
19
3
  const visibleIds = new Set();
20
4
  function collectVisible(nodes) {
21
5
  for (const nav of nodes) {
22
- if (isHidden(nav.hidden) || hiddenNav.includes(nav.slug) || hiddenNav.includes(nav.navUuid)) continue;
6
+ if (nav.hidden || hiddenNav.includes(nav.slug) || hiddenNav.includes(nav.navUuid)) continue;
23
7
  if (nav.navUuid) visibleIds.add(nav.navUuid);
24
- if (nav.formUuid) visibleIds.add(nav.formUuid);
25
8
  collectVisible(nav.children || []);
26
9
  }
27
10
  }
28
- if (mode === 'platform') collectVisible(navs);
29
- const validRequirement = requirement => requirement && typeof requirement.formUuid === 'string' && requirement.formUuid.trim()
30
- && typeof requirement.operation === 'string' && requirement.operation.trim()
31
- && (requirement.viewUuid === undefined || (typeof requirement.viewUuid === 'string' && requirement.viewUuid.trim()));
32
- const grantKey = requirement => JSON.stringify([requirement.formUuid, requirement.viewUuid || '', requirement.operation]);
33
- const grants = new Map();
34
- for (const grant of access?.grants || []) {
35
- if (!validRequirement(grant)) continue;
36
- const key = grantKey(grant);
37
- // 重复结果存在拒绝或未知时,不采用其中的允许结果。
38
- grants.set(key, grant.allowed === true && grants.get(key) !== false);
39
- }
40
- function allowed(item, leaf) {
41
- const requirements = item.access;
42
- if (requirements === undefined) return mode === 'local' || mode === 'platform' || (!leaf && !item.formUuid && !item.navUuid);
43
- if (!Array.isArray(requirements) || !requirements.length || !requirements.every(validRequirement)) return false;
44
- if (leaf && mode !== 'local') {
45
- const operation = item.targetType === 'submission' ? 'OPERATE_CREATE' : 'OPERATE_VIEW';
46
- if (!item.formUuid || !requirements.some(requirement => requirement.formUuid === item.formUuid
47
- && (requirement.viewUuid || '') === (item.viewUuid || item.params?.viewUuid || '') && requirement.operation === operation)) return false;
48
- }
49
- return requirements.every(requirement => grants.get(grantKey(requirement)) === true);
50
- }
11
+ collectVisible(navs);
51
12
  function filterItems(nodes) {
52
13
  return nodes.flatMap(item => {
53
14
  const resourceId = item.navUuid || item.formUuid;
54
- if (isHidden(item.hidden) || (mode === 'platform' && resourceId && !visibleIds.has(resourceId))) return [];
55
- if (item.children !== undefined && !Array.isArray(item.children)) return [];
15
+ if (item.hidden || (resourceId && !visibleIds.has(resourceId))) return [];
56
16
  if (item.children?.length) {
57
- if (!allowed(item, false)) return [];
58
17
  const children = filterItems(item.children);
59
18
  return children.length ? [{ ...item, children }] : [];
60
19
  }
61
- if (!allowed(item, true)) return [];
62
- return mode !== 'platform' || visibleIds.has(resourceId) ? [item] : [];
20
+ return visibleIds.has(resourceId) ? [item] : [];
63
21
  });
64
22
  }
65
23
  return filterItems(items);
66
24
  }
67
25
 
68
- /** 只在过滤后的叶子菜单中选择内容;无可用入口时返回 undefined。 */
69
- function selectCanvasNavigation(items, requestedKey, defaultKey) {
70
- const leaves = [];
71
- function collect(nodes) {
72
- for (const item of nodes) {
73
- if (item.children?.length) collect(item.children);
74
- else if (!item.disabled) leaves.push(item);
75
- }
76
- }
77
- collect(items);
78
- return leaves.find(item => item.key === requestedKey) || leaves.find(item => item.key === defaultKey) || leaves[0];
79
- }
80
-
81
- /** 用途决定路由;独立页面走 custom,管理视图保留真实 viewUuid。 */
26
+ /** 按入口任务选择提交页或管理页;targetType 由 PRD 明确,表单类型不决定入口用途。 */
82
27
  function buildCanvasNavigationUrl(item, appType, { embedded = false } = {}) {
83
28
  if (item.targetType === 'url') return item.url;
84
- if (!['submission', 'page', 'custom'].includes(item.targetType)) throw new Error('请明确导航入口用途');
29
+ if (!['submission', 'page'].includes(item.targetType)) throw new Error('请明确导航入口用途');
85
30
  const formUuid = item.formUuid || item.navUuid;
86
31
  if (!appType || !formUuid) throw new Error('缺少导航目标');
87
32
  const query = new URLSearchParams(item.params || {});
88
- const route = { submission: 'submission', page: 'workbench', custom: 'custom' }[item.targetType];
89
- if (item.viewUuid) {
90
- if (route !== 'workbench') throw new Error('管理视图必须使用 workbench 入口');
91
- query.set('viewUuid', item.viewUuid);
92
- }
93
- if (route === 'custom') query.delete('isRenderNav');
33
+ const route = item.targetType === 'submission' ? 'submission' : 'workbench';
94
34
  if (embedded) {
95
- if (route === 'workbench') query.set('iframe', 'true');
96
- else query.set('isRenderNav', 'false');
35
+ if (route === 'submission') query.set('isRenderNav', 'false');
36
+ else query.set('iframe', 'true');
97
37
  }
98
38
  const suffix = query.toString();
99
39
  return `/${encodeURIComponent(appType)}/${route}/${encodeURIComponent(formUuid)}${suffix ? '?' + suffix : ''}`;
100
40
  }
101
41
 
102
- /** resolveAccess 是调用方对真实权限服务的适配,不是平台已有的接口或静态授权清单。 */
103
- async function loadCanvasNavigation({ items, appType, formUuid, csrfToken, hiddenNav = [], signal, mode = 'platform', resolveAccess }) {
42
+ /** 使用当前访问者的登录态读取导航;csrfToken、hiddenNav 由当前页面运行态提供。 */
43
+ async function loadCanvasNavigation({ items, appType, formUuid, csrfToken, hiddenNav = [], signal }) {
104
44
  if (!Array.isArray(items)) throw new Error('缺少 PRD 导航配置');
105
- validateCanvasNavigationItems(items, mode);
106
- if (mode !== 'local' && !appType) throw new Error('缺少应用标识');
107
- let needsAccess = mode === 'independent';
108
- const requirements = [];
109
- function collect(nodes) {
110
- for (const item of nodes) {
111
- if (item.access !== undefined) {
112
- needsAccess = true;
113
- if (Array.isArray(item.access)) requirements.push(...item.access);
114
- }
115
- if (Array.isArray(item.children)) collect(item.children);
116
- }
117
- }
118
- collect(items);
119
- let access;
120
- if (needsAccess) {
121
- if (!appType) throw new Error('权限查询需要应用标识');
122
- if (typeof resolveAccess !== 'function') throw new Error('缺少当前访问者的权限查询能力');
123
- access = await resolveAccess({ appType, requirements, signal });
124
- if (access?.appType !== appType || !Array.isArray(access.grants)) throw new Error('权限查询失败,请重试');
125
- }
126
- if (signal?.aborted) throw new Error('导航加载已取消');
127
- // 独立菜单不依赖平台树是否含有被隐藏的资源;授权必须来自上述实时权限查询。
128
- if (mode !== 'platform') return filterCanvasNavigation(items, [], [], { mode, access });
45
+ if (!appType) throw new Error('缺少应用标识');
129
46
  const query = new URLSearchParams({ _api: 'nattyFetch', _mock: 'false' });
130
47
  if (formUuid) query.set('formUuid', formUuid);
131
48
  if (csrfToken) query.set('_csrf_token', csrfToken);
@@ -136,7 +53,8 @@ async function loadCanvasNavigation({ items, appType, formUuid, csrfToken, hidde
136
53
  });
137
54
  if (!response.ok) throw new Error('导航加载失败,请重试');
138
55
  const result = await response.json();
139
- if (result.success !== true || !Array.isArray(result.content?.navs)) throw new Error('导航加载失败,请重试');
140
- if (signal?.aborted) throw new Error('导航加载已取消');
141
- return filterCanvasNavigation(items, result.content.navs, hiddenNav, { mode, access });
56
+ if (result.success !== true || !Array.isArray(result.content?.navs)) {
57
+ throw new Error('导航加载失败,请重试');
58
+ }
59
+ return filterCanvasNavigation(items, result.content.navs, hiddenNav);
142
60
  }
@@ -4,14 +4,12 @@ function CanvasNav({ items = [], activeKey, onSelect, title, logo, actions, chil
4
4
  return <div className="oy-canvas-nav oy-nav-mixed">
5
5
  <style>{CANVAS_NAV_CSS + `
6
6
  .oy-nav-mixed { display: flex; flex-direction: column; }
7
- .oy-nav-mixed .oy-nav-header { box-sizing: border-box; min-height: var(--pod-nav-platform-header-height, 48px); display: flex; flex-wrap: wrap; align-items: center; gap: var(--pod-nav-l-header-gap, 24px); padding: var(--pod-nav-l-header-padding, 8px 16px); border-bottom: 1px solid var(--pod-nav-sub-divider-color, var(--color-line1-1, #ddd)); }
8
- .oy-nav-mixed .oy-nav-groups { display: flex; flex: 1; min-width: 0; gap: var(--pod-nav-menu-gap, 8px); padding: calc(var(--pod-nav-menu-gap, 8px) / 2); overflow-x: auto; }
9
- .oy-nav-mixed .oy-nav-groups .oy-nav-item { min-height: var(--pod-nav-top-tab-height, 40px); padding: var(--pod-nav-top-tab-item-padding, 0 12px); max-width: var(--pod-nav-top-tab-item-max-width, 240px); }
10
- .oy-nav-mixed .oy-nav-groups .oy-nav-item > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
7
+ .oy-nav-mixed .oy-nav-header { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pod-nav-l-header-gap, 24px); padding: var(--pod-nav-l-header-padding, 8px 16px); border-bottom: 1px solid var(--pod-nav-sub-divider-color, var(--color-line1-1, #ddd)); }
8
+ .oy-nav-mixed .oy-nav-groups { display: flex; flex: 1; min-width: 0; overflow-x: auto; }
11
9
  .oy-nav-mixed .oy-nav-body { display: flex; flex: 1; }
12
- .oy-canvas-nav.oy-nav-mixed .oy-nav-sidebar { padding: var(--pod-nav-l-aside-padding, 8px); }
13
10
  .oy-nav-mixed .oy-nav-content { flex: 1; }
14
- .oy-nav-mixed .oy-nav-menu { display: flex; flex-direction: column; gap: var(--pod-nav-menu-gap, 8px); }
11
+ .oy-nav-mixed .oy-nav-menu { display: flex; flex-direction: column; gap: var(--pod-nav-slide-aside-gap, 12px); }
12
+ .oy-nav-mixed .oy-nav-item[aria-current="page"] { box-shadow: inset 0 -2px var(--pod-nav-tab-line-selected-color, var(--color-brand1-6, #1677ff)); }
15
13
  @media (max-width: 767px) {
16
14
  .oy-nav-mixed .oy-nav-groups { flex-basis: 100%; }
17
15
  .oy-nav-mixed .oy-nav-body { display: block; }
@@ -14,12 +14,12 @@ const CANVAS_NAV_CSS = `
14
14
  .oy-canvas-nav .oy-nav-brand > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
15
15
  .oy-canvas-nav .oy-nav-item {
16
16
  box-sizing: border-box; display: flex; flex-shrink: 0; align-items: center; gap: var(--pod-nav-logo-gap, 8px);
17
- min-height: var(--pod-nav-menu-item-height, 40px); padding: var(--pod-nav-menu-item-padding, 8px 12px);
18
- border: var(--pod-nav-menu-item-border, none); border-radius: var(--pod-nav-menu-item-radius, 8px); background: transparent;
19
- color: var(--pod-nav-item-text-color, var(--color-text1-4, #1f2329)); font: inherit; font-size: var(--pod-nav-menu-font-size, 14px); line-height: var(--pod-nav-menu-line-height, 20px); text-decoration: none; text-align: start; cursor: pointer;
17
+ min-height: var(--pod-nav-menu-item-height, 40px); padding: var(--pod-nav-top-tab-item-padding, 0 12px);
18
+ border: 0; border-radius: var(--pod-nav-menu-item-radius, 8px); background: transparent;
19
+ color: var(--pod-nav-item-text-color, var(--color-text1-4, #1f2329)); font: inherit; font-size: var(--pod-nav-menu-font-size, 14px); text-decoration: none; text-align: start; cursor: pointer;
20
20
  }
21
- .oy-canvas-nav .oy-nav-item:hover:not(:disabled) { border: var(--pod-nav-menu-item-hover-border, var(--pod-nav-menu-item-border, none)); background: var(--pod-nav-menu-bg-hover-color, var(--color-fill1-2, #f2f3f5)); color: var(--pod-nav-item-text-hover-color, inherit); }
22
- .oy-canvas-nav .oy-nav-item[aria-current="page"], .oy-canvas-nav .oy-nav-item[aria-current="page"]:hover { border: var(--pod-nav-menu-item-selected-border, var(--pod-nav-menu-item-border, none)); box-shadow: var(--pod-nav-menu-item-selected-shadow, none); background: var(--pod-nav-menu-bg-selected-color, var(--color-brand1-1, #e8f2ff)); color: var(--pod-nav-item-text-selected-color, var(--color-brand1-6, #1677ff)); font-weight: var(--pod-nav-menu-item-selected-font-weight, 600); }
21
+ .oy-canvas-nav .oy-nav-item:hover:not(:disabled) { background: var(--pod-nav-menu-bg-hover-color, var(--color-fill1-2, #f2f3f5)); color: var(--pod-nav-item-text-hover-color, inherit); }
22
+ .oy-canvas-nav .oy-nav-item[aria-current="page"] { background: var(--pod-nav-menu-bg-selected-color, var(--color-brand1-1, #e8f2ff)); color: var(--pod-nav-item-text-selected-color, var(--color-brand1-6, #1677ff)); font-weight: var(--pod-nav-menu-item-selected-font-weight, 600); }
23
23
  .oy-canvas-nav .oy-nav-item:disabled { color: var(--pod-nav-item-text-disabled-color, var(--color-text1-1, #999)); cursor: not-allowed; }
24
24
  .oy-canvas-nav .oy-nav-item:focus-visible { outline: 2px solid var(--pod-nav-tab-line-selected-color, var(--color-brand1-6, #1677ff)); outline-offset: -2px; }
25
25
  .oy-canvas-nav .oy-nav-item svg { flex-shrink: 0; width: var(--pod-nav-platform-action-icon-size, 18px); height: var(--pod-nav-platform-action-icon-size, 18px); }
@@ -5,7 +5,8 @@ function CanvasNav({ items = [], activeKey, onSelect, title, logo, actions, chil
5
5
  .oy-nav-side { display: flex; }
6
6
  .oy-nav-side .oy-nav-content { flex: 1; }
7
7
  .oy-nav-side .oy-nav-brand { min-height: var(--pod-nav-platform-header-height, 48px); }
8
- .oy-nav-side .oy-nav-menu { display: flex; flex-direction: column; gap: var(--pod-nav-menu-gap, 8px); }
8
+ .oy-nav-side .oy-nav-menu { display: flex; flex-direction: column; gap: var(--pod-nav-slide-aside-gap, 12px); }
9
+ .oy-nav-side .oy-nav-item[aria-current="page"] { box-shadow: inset 3px 0 var(--pod-nav-tab-line-selected-color, var(--color-brand1-6, #1677ff)); }
9
10
  @media (max-width: 767px) { .oy-nav-side { display: block; } }
10
11
  `}</style>
11
12
  <CanvasSidebar title={title} logo={logo} actions={actions} activeKey={activeKey} defaultWidth={sidebarWidth} defaultCollapsed={defaultCollapsed}>
@@ -41,7 +41,7 @@ function CanvasSidebar({ children, title, logo, actions, activeKey, defaultWidth
41
41
  onClick={event => { if (mobile && event.target.closest('.oy-nav-menu .oy-nav-item')) setMobileOpen(false); }}
42
42
  style={{ '--oy-sidebar-width': width === null ? (typeof defaultWidth === 'number' ? `${defaultWidth}px` : defaultWidth) : `${clamp(width)}px`, '--oy-sidebar-max-width': `${maxWidth}px` }}>
43
43
  <style>{`
44
- .oy-canvas-nav .oy-nav-sidebar { position: relative; box-sizing: border-box; flex: 0 0 auto; min-width: 0; width: clamp(180px, var(--oy-sidebar-width, var(--shell-dark-aside-width, 216px)), var(--oy-sidebar-max-width, 400px)); padding: var(--pod-nav-slide-aside-padding, 8px); border-right: 1px solid var(--pod-nav-sub-divider-color, var(--color-line1-1, #ddd)); }
44
+ .oy-canvas-nav .oy-nav-sidebar { position: relative; box-sizing: border-box; flex: 0 0 auto; min-width: 0; width: clamp(180px, var(--oy-sidebar-width, var(--shell-dark-aside-width, 216px)), var(--oy-sidebar-max-width, 400px)); padding: var(--pod-nav-l-aside-padding, 8px); border-right: 1px solid var(--pod-nav-sub-divider-color, var(--color-line1-1, #ddd)); }
45
45
  .oy-canvas-nav .oy-sidebar-toggle { margin-left: auto; flex-shrink: 0; justify-content: center; padding: 0 8px; }
46
46
  .oy-canvas-nav .oy-sidebar-items { min-width: 0; }
47
47
  .oy-canvas-nav .oy-nav-sidebar .oy-nav-item > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -1,23 +1,17 @@
1
1
  import { Menu } from 'lucide-react';
2
2
 
3
- /** 顶部导航默认贴边通栏;明确选择悬浮样式时传 floating=true。窄屏可展开菜单。 */
4
- function CanvasNav({ items = [], activeKey, onSelect, title, logo, actions, children, floating = false, headerOnly = false, overlay = false }) {
3
+ /** 顶部导航默认使用浮导;floating=false 时使用贴边通栏,窄屏通过按钮展开菜单。 */
4
+ function CanvasNav({ items = [], activeKey, onSelect, title, logo, actions, children, floating = true }) {
5
5
  const [expanded, setExpanded] = React.useState(false);
6
6
  const menuId = React.useId();
7
7
  React.useEffect(() => setExpanded(false), [activeKey]);
8
- return <div className={'oy-canvas-nav oy-nav-top' + (floating ? ' is-floating' : '') + (headerOnly ? ' is-header-only' : '') + (overlay ? ' is-overlay' : '')}>
8
+ return <div className={'oy-canvas-nav oy-nav-top' + (floating ? ' is-floating' : '')}>
9
9
  <style>{CANVAS_NAV_CSS + `
10
- .oy-nav-top .oy-nav-header { box-sizing: border-box; min-height: var(--pod-nav-platform-header-height, 48px); display: flex; flex-wrap: wrap; align-items: center; gap: var(--pod-nav-top-header-gap, 24px); padding: var(--pod-nav-top-header-padding, 8px 16px); border-bottom: 1px solid var(--pod-nav-sub-divider-color, var(--color-line1-1, #ddd)); }
11
- .oy-nav-top.is-header-only { min-height: 0; background: transparent; }
12
- .openyida-nav-layout[data-layout="document"][data-scrolled="false"] .oy-nav-top.is-overlay .oy-nav-header:not(.is-expanded) { background: transparent; color: var(--openyida-navigation-overlay-color, #fff); border-color: transparent; }
13
- .openyida-nav-layout[data-layout="document"][data-scrolled="false"] .oy-nav-top.is-overlay .oy-nav-header:not(.is-expanded) .oy-nav-brand,
14
- .openyida-nav-layout[data-layout="document"][data-scrolled="false"] .oy-nav-top.is-overlay .oy-nav-header:not(.is-expanded) .oy-nav-item:not(:disabled) { color: inherit; }
15
- .openyida-nav-layout[data-layout="document"][data-scrolled="false"] .oy-nav-top.is-overlay .oy-nav-header:not(.is-expanded) .oy-nav-item:is(:hover,[aria-current="page"]):not(:disabled) { background: var(--openyida-navigation-overlay-active-bg, rgba(255,255,255,.16)); }
10
+ .oy-nav-top .oy-nav-header { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pod-nav-top-header-gap, 24px); padding: var(--pod-nav-top-header-padding, 8px 16px); border-bottom: 1px solid var(--pod-nav-sub-divider-color, var(--color-line1-1, #ddd)); }
16
11
  .oy-nav-top.is-floating { padding-top: 16px; box-sizing: border-box; }
17
- .oy-nav-top.is-floating .oy-nav-header { position: sticky; top: 16px; z-index: 10; margin: 0 16px; border: 1px solid var(--pod-nav-sub-divider-color, var(--color-line1-1, #ddd)); border-radius: var(--pod-shell-lshape-border-radius, 16px); box-shadow: var(--pod-nav-popup-shadow, 0 8px 24px rgba(0,0,0,.12)); }
18
- .oy-nav-top .oy-nav-menu { display: flex; flex: 1; min-width: 0; gap: var(--pod-nav-menu-gap, 8px); padding: calc(var(--pod-nav-menu-gap, 8px) / 2); overflow-x: auto; }
19
- .oy-nav-top .oy-nav-menu .oy-nav-item { min-height: var(--pod-nav-top-tab-height, 40px); padding: var(--pod-nav-top-tab-item-padding, 0 12px); max-width: var(--pod-nav-top-tab-item-max-width, 240px); }
20
- .oy-nav-top .oy-nav-menu .oy-nav-item > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
12
+ .oy-nav-top.is-floating .oy-nav-header { position: sticky; top: 16px; z-index: 10; margin: 0 16px; border: 1px solid var(--pod-nav-sub-divider-color, var(--color-line1-1, #ddd)); border-radius: var(--pod-nav-menu-container-radius, 16px); box-shadow: var(--pod-nav-popup-shadow, 0 8px 24px rgba(0,0,0,.12)); }
13
+ .oy-nav-top .oy-nav-menu { display: flex; flex: 1; min-width: 0; overflow-x: auto; }
14
+ .oy-nav-top .oy-nav-item[aria-current="page"] { box-shadow: inset 0 -2px var(--pod-nav-tab-line-selected-color, var(--color-brand1-6, #1677ff)); }
21
15
  .oy-nav-top .oy-nav-toggle { display: none; margin-left: auto; }
22
16
  @media (max-width: 767px) {
23
17
  .oy-nav-top .oy-nav-header { gap: var(--pod-nav-logo-gap, 8px); }
@@ -26,12 +20,12 @@ function CanvasNav({ items = [], activeKey, onSelect, title, logo, actions, chil
26
20
  .oy-nav-top .oy-nav-menu:not(.is-expanded) { display: none; }
27
21
  }
28
22
  `}</style>
29
- <header className={'oy-nav-header oy-nav-surface' + (expanded ? ' is-expanded' : '')}>
23
+ <header className="oy-nav-header oy-nav-surface">
30
24
  <div className="oy-nav-brand">{logo}<span>{title}</span></div>
31
25
  <button className="oy-nav-item oy-nav-toggle" type="button" aria-label={expanded ? '收起导航' : '展开导航'} aria-controls={menuId} aria-expanded={expanded} onClick={() => setExpanded(!expanded)}><Menu aria-hidden="true" /></button>
32
26
  <nav id={menuId} aria-label="应用导航" className={'oy-nav-menu' + (expanded ? ' is-expanded' : '')}>{items.map(item => <CanvasNavItem key={item.key} item={item} activeKey={activeKey} onSelect={onSelect ? (selected) => { setExpanded(false); onSelect(selected); } : undefined} />)}</nav>
33
27
  {actions}
34
28
  </header>
35
- {!headerOnly && <main className="oy-nav-content" aria-label={items.find(item => item.key === activeKey)?.label}>{children}</main>}
29
+ <main className="oy-nav-content" aria-label={items.find(item => item.key === activeKey)?.label}>{children}</main>
36
30
  </div>;
37
31
  }
@@ -110,10 +110,86 @@ function getBridgeState(props) {
110
110
  return { ready: true, reason: '', writeBridge, fieldMap };
111
111
  }
112
112
 
113
- /* @canvas-application-theme */
113
+ // @openyida-canvas-theme:start
114
+ // Standalone samples keep this fragment identical; see canvas-theme.test.js.
115
+ function readCanvasTheme(root, fallback) {
116
+ const roles = {
117
+ colorPrimary: '--color-brand1-6', colorLink: '--color-brand1-6',
118
+ colorPrimaryHover: '--color-brand1-5', colorPrimaryActive: '--color-brand1-9',
119
+ colorBgLayout: ['--pod-page-bg-color', '--color-white'],
120
+ colorBgContainer: ['--pod-card-bg-color', '--color-white'],
121
+ colorBgElevated: ['--pod-card-bg-color', '--color-white'], colorText: '--color-text1-4',
122
+ colorTextHeading: '--color-text1-4', colorTextSecondary: '--color-text1-3',
123
+ colorTextDescription: '--color-text1-3', colorTextPlaceholder: '--color-text1-10',
124
+ colorBorder: '--color-line1-2', colorBorderSecondary: '--color-line1-1',
125
+ colorFillAlter: '--color-fill1-1', colorFillSecondary: '--color-fill1-2',
126
+ };
127
+ const token = { ...fallback };
128
+ if (!root) return token;
129
+ const doc = root.ownerDocument;
130
+ const view = doc.defaultView;
131
+ const scope = view.getComputedStyle(root);
132
+ const probe = doc.createElement('span');
133
+ probe.style.cssText = 'position:absolute;visibility:hidden;pointer-events:none;';
134
+ root.appendChild(probe);
135
+ try {
136
+ Object.keys(roles).forEach((role) => {
137
+ const names = Array.isArray(roles[role]) ? roles[role] : [roles[role]];
138
+ const value = names.map((name) => scope.getPropertyValue(name).trim()).find(Boolean) || '';
139
+ if (!value || !view.CSS.supports('color', value)) return;
140
+ probe.style.color = value;
141
+ const color = view.getComputedStyle(probe).color;
142
+ if (color) token[role] = color;
143
+ });
144
+ } finally {
145
+ probe.remove();
146
+ }
147
+ return token;
148
+ }
149
+
150
+ function useCanvasTheme(fallback) {
151
+ const rootRef = React.useRef(null);
152
+ const fallbackRef = React.useRef(fallback);
153
+ const [token, setToken] = React.useState(fallback);
154
+ React.useLayoutEffect(() => {
155
+ const root = rootRef.current;
156
+ if (!root) return undefined;
157
+ const doc = root.ownerDocument;
158
+ const view = doc.defaultView;
159
+ let frame;
160
+ const refresh = () => {
161
+ const next = readCanvasTheme(root, fallbackRef.current);
162
+ setToken((previous) => JSON.stringify(previous) === JSON.stringify(next) ? previous : next);
163
+ };
164
+ const schedule = () => {
165
+ view.cancelAnimationFrame(frame);
166
+ frame = view.requestAnimationFrame(refresh);
167
+ };
168
+ refresh();
169
+ // Observe only theme-bearing ancestors and stylesheet changes, not business DOM.
170
+ const observer = new view.MutationObserver(schedule);
171
+ for (let node = root; node; node = node.parentElement) {
172
+ observer.observe(node, { attributes: true });
173
+ }
174
+ if (doc.head) observer.observe(doc.head, { subtree: true, childList: true, characterData: true, attributes: true });
175
+ doc.addEventListener('load', schedule, true);
176
+ view.addEventListener('resize', schedule);
177
+ view.addEventListener('openyida:theme-change', schedule);
178
+ return () => {
179
+ observer.disconnect();
180
+ view.cancelAnimationFrame(frame);
181
+ doc.removeEventListener('load', schedule, true);
182
+ view.removeEventListener('resize', schedule);
183
+ view.removeEventListener('openyida:theme-change', schedule);
184
+ };
185
+ }, []);
186
+ return { rootRef, token };
187
+ }
188
+ // @openyida-canvas-theme:end
114
189
 
115
- function PageContent(props) {
190
+ function YidaComp(props) {
116
191
  const [modal, modalContextHolder] = Modal.useModal();
192
+ const { rootRef, token } = useCanvasTheme({ colorPrimary: "#1677ff", borderRadius: 9 });
117
193
  const formUuid = props && props.formUuid ? props.formUuid : 'sample-unbound';
118
194
  const draftKey = 'openyida_canvas_table_form_draft_' + formUuid;
119
195
  const [rows, setRows] = useState(() => loadDraft(draftKey));
@@ -383,7 +459,9 @@ function PageContent(props) {
383
459
  const pendingCount = rows.filter((row) => row._status !== 'submitted').length;
384
460
 
385
461
  return (
386
- <>
462
+ <ConfigProvider
463
+ theme={{ token }}
464
+ >
387
465
  <style>{`
388
466
  .canvas-table-page {
389
467
  display: flow-root;
@@ -425,7 +503,7 @@ function PageContent(props) {
425
503
  }
426
504
  `}</style>
427
505
 
428
- <div className="canvas-table-page">
506
+ <div ref={rootRef} className="canvas-table-page">
429
507
  {modalContextHolder}
430
508
  <div className="canvas-table-shell">
431
509
  <div className="canvas-table-header">
@@ -498,12 +576,8 @@ function PageContent(props) {
498
576
  </div>
499
577
  </div>
500
578
  </div>
501
- </>
579
+ </ConfigProvider>
502
580
  );
503
581
  }
504
582
 
505
- function YidaComp(props) {
506
- return <CanvasThemeProvider><PageContent {...props} /></CanvasThemeProvider>;
507
- }
508
-
509
583
  export default YidaComp;