@birdapi/velinstyle 1.1.0 → 1.2.1

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 (328) hide show
  1. package/README.de.md +89 -161
  2. package/README.md +187 -119
  3. package/cli/blueprint.js +98 -5
  4. package/cli/blueprints/app-chrome.html +18 -0
  5. package/cli/blueprints/benefits-grid.html +9 -0
  6. package/cli/blueprints/bottom-nav-mobile.html +2 -1
  7. package/cli/blueprints/cookie-consent.html +1 -1
  8. package/cli/blueprints/cta-band.html +6 -0
  9. package/cli/blueprints/faq-section.html +18 -0
  10. package/cli/blueprints/filter-bar.html +4 -4
  11. package/cli/blueprints/form-contact.html +6 -5
  12. package/cli/blueprints/hero-section.html +3 -3
  13. package/cli/blueprints/notification-center.html +1 -1
  14. package/cli/blueprints/onboarding.html +2 -1
  15. package/cli/blueprints/ops-console.html +29 -0
  16. package/cli/blueprints/pricing-band.html +37 -0
  17. package/cli/blueprints/process-steps.html +10 -0
  18. package/cli/blueprints/services-grid.html +9 -0
  19. package/cli/blueprints/settings-panel.html +8 -6
  20. package/cli/blueprints/split-hero.html +25 -0
  21. package/cli/blueprints/testimonials.html +8 -0
  22. package/cli/blueprints/trust-bar.html +10 -0
  23. package/cli/cli-manifest.json +81 -17
  24. package/cli/contrast-utils.js +97 -0
  25. package/cli/create.js +370 -0
  26. package/cli/docgen/extract-attributes.js +128 -10
  27. package/cli/docgen/extract-cli.js +3 -2
  28. package/cli/docgen/extract-components.js +61 -2
  29. package/cli/docgen/extract-utilities.js +10 -10
  30. package/cli/doctor.js +119 -0
  31. package/cli/index.js +560 -44
  32. package/cli/meta.js +84 -1
  33. package/cli/perf-audit.js +15 -2
  34. package/cli/prompt-engine.js +243 -0
  35. package/cli/review.js +268 -0
  36. package/cli/scaffold.js +119 -4
  37. package/cli/scanner-rules-data.js +7 -0
  38. package/cli/scanner.js +357 -4
  39. package/cli/serve.js +81 -0
  40. package/cli/skills.js +223 -0
  41. package/cli/transparency.js +221 -0
  42. package/cli/wc-api.js +89 -0
  43. package/cli/workflow.js +42 -0
  44. package/components/index.js +2 -0
  45. package/components/runtime/component-loaders.js +2 -0
  46. package/components/velin-accordion.js +62 -13
  47. package/components/velin-bottom-nav.js +10 -0
  48. package/components/velin-calendar.js +212 -0
  49. package/components/velin-command.js +18 -2
  50. package/components/velin-data-table.js +78 -1
  51. package/components/velin-dialog.js +4 -1
  52. package/components/velin-drawer.js +2 -4
  53. package/components/velin-file-dropzone.js +162 -0
  54. package/components/velin-icon.js +22 -1
  55. package/components/velin-lightbox.js +5 -3
  56. package/components/velin-modal.js +2 -4
  57. package/components/velin-search.js +1 -1
  58. package/components/velin-sheet.js +2 -4
  59. package/core/a11y/component-contracts.json +20 -3
  60. package/core/attributes/registry.js +14 -0
  61. package/core/meta/build.js +125 -5
  62. package/core/meta/design-constraints/contact.json +9 -0
  63. package/core/meta/design-constraints/faq.json +9 -0
  64. package/core/meta/design-constraints/hero.json +13 -0
  65. package/core/meta/knowledge/components.json +622 -0
  66. package/core/meta/knowledge/tokens.json +282 -0
  67. package/core/meta/pages/registry.json +294 -0
  68. package/core/meta/schema.js +13 -1
  69. package/core/meta/sections/registry.json +185 -0
  70. package/core/transparency/attach.js +74 -0
  71. package/core/transparency/claims.js +97 -0
  72. package/core/transparency/doctor.js +142 -0
  73. package/core/transparency/engine.js +75 -0
  74. package/core/transparency/export.js +98 -0
  75. package/core/transparency/index.js +30 -0
  76. package/core/transparency/migrate.js +130 -0
  77. package/core/transparency/normalize.js +125 -0
  78. package/core/transparency/policy.js +105 -0
  79. package/core/transparency/providers.js +235 -0
  80. package/core/transparency/registry.js +104 -0
  81. package/core/transparency/renderer.js +111 -0
  82. package/core/transparency/reporter.js +113 -0
  83. package/core/transparency/validator.js +112 -0
  84. package/dist/chunks/attach-H2ZSEAE6.js +365 -0
  85. package/dist/chunks/{attributes-STYCS3O5.js → attributes-A423NX5J.js} +3 -3
  86. package/dist/chunks/attributes-DZCXX2RZ.js +404 -0
  87. package/dist/chunks/{attributes-353XDOAX.js → attributes-F6UPIEVP.js} +1 -1
  88. package/dist/chunks/{attributes-ADOKLKA7.js → attributes-GLYXGGAL.js} +3 -3
  89. package/dist/chunks/{attributes-TPANLMLF.js → attributes-UFTYOSAU.js} +3 -3
  90. package/dist/chunks/attributes-XGLXLR2T.js +391 -0
  91. package/dist/chunks/attributes-YF4NI2QS.js +391 -0
  92. package/dist/chunks/browser-AUABBYUK.js +1544 -0
  93. package/dist/chunks/{chunk-RSMRR27R.js → chunk-2LSKX57P.js} +12 -10
  94. package/dist/chunks/{chunk-IEHKRARD.js → chunk-2TGCVDUL.js} +11 -9
  95. package/dist/chunks/{chunk-SRL6EWHP.js → chunk-5JWGUAPC.js} +17 -13
  96. package/dist/chunks/chunk-7YSO2OQ2.js +113 -0
  97. package/dist/chunks/{chunk-QVHYL3R4.js → chunk-BHR3ZG6U.js} +6 -6
  98. package/dist/chunks/chunk-CQMTCEI6.js +113 -0
  99. package/dist/chunks/{chunk-J472ERN2.js → chunk-JMSIHEYX.js} +15 -4
  100. package/dist/chunks/{chunk-MKZP2TBH.js → chunk-L7ZGUU4D.js} +2 -2
  101. package/dist/chunks/chunk-TUGIPKW5.js +113 -0
  102. package/dist/chunks/{highlight-GJHHV4KM.js → highlight-M2ELQNYK.js} +1 -1
  103. package/dist/chunks/runtime-entry.js +1 -1
  104. package/dist/chunks/{velin-accordion-FBIPAEXG.js → velin-accordion-WSY6BMLA.js} +64 -10
  105. package/dist/chunks/{velin-bottom-nav-7GEMPIM6.js → velin-bottom-nav-5RVRNGIP.js} +25 -0
  106. package/dist/chunks/{velin-bottom-nav-N3DFQR66.js → velin-bottom-nav-N5F4UO2I.js} +26 -1
  107. package/dist/chunks/velin-calendar-OFE6THUD.js +210 -0
  108. package/dist/chunks/velin-calendar-PGVNJTXK.js +217 -0
  109. package/dist/chunks/velin-calendar-XC7JRDSH.js +217 -0
  110. package/dist/chunks/{velin-code-block-CIAURDRJ.js → velin-code-block-ZGWG7JI5.js} +1 -1
  111. package/dist/chunks/{velin-combobox-NXS4QB4R.js → velin-combobox-56V2ZWT5.js} +1 -1
  112. package/dist/chunks/{velin-command-ONKO2A3J.js → velin-command-2HO2EKR6.js} +29 -2
  113. package/dist/chunks/{velin-command-TMLSRGIU.js → velin-command-ZJSLPK7B.js} +30 -3
  114. package/dist/chunks/{velin-copy-NYDBOKXT.js → velin-copy-XDQSV2XU.js} +1 -1
  115. package/dist/chunks/{velin-countdown-4ZVDGK4R.js → velin-countdown-V4Z5MA63.js} +1 -1
  116. package/dist/chunks/velin-data-table-UVR42UUM.js +372 -0
  117. package/dist/chunks/{velin-dialog-GTTZI564.js → velin-dialog-3YK2RPRV.js} +9 -2
  118. package/dist/chunks/{velin-dialog-ELFOZIXZ.js → velin-dialog-S24KAP4S.js} +3 -1
  119. package/dist/chunks/{velin-drawer-BE6TYN3H.js → velin-drawer-5PNU624J.js} +2 -4
  120. package/dist/chunks/{velin-drawer-DLL2GLT6.js → velin-drawer-CCM6S25D.js} +3 -5
  121. package/dist/chunks/{velin-email-RBX6ZR4S.js → velin-email-TNFONXPW.js} +1 -1
  122. package/dist/chunks/velin-file-dropzone-QRGF2JNA.js +154 -0
  123. package/dist/chunks/velin-file-dropzone-XIZMJ3NB.js +154 -0
  124. package/dist/chunks/{velin-icon-7M76DOPB.js → velin-icon-A6NCXGUK.js} +59 -17
  125. package/dist/chunks/{velin-icon-ZTSKUOVN.js → velin-icon-EC4B5XCM.js} +18 -5
  126. package/dist/chunks/{velin-lightbox-6E7CAATP.js → velin-lightbox-FFK4TUUP.js} +7 -6
  127. package/dist/chunks/{velin-lightbox-NXA3U2FM.js → velin-lightbox-P725FLTY.js} +5 -4
  128. package/dist/chunks/{velin-menubar-J66JXRWW.js → velin-menubar-6I2LM5HL.js} +1 -1
  129. package/dist/chunks/{velin-modal-5HYNNNUI.js → velin-modal-ICTMGRSU.js} +7 -8
  130. package/dist/chunks/{velin-modal-AEOTZ67O.js → velin-modal-JBNODH7D.js} +2 -4
  131. package/dist/chunks/{velin-popover-T72HK3DF.js → velin-popover-WZG2GHBL.js} +25 -4
  132. package/dist/chunks/{velin-rating-N4DI2XNL.js → velin-rating-QBBYRRBU.js} +1 -1
  133. package/dist/chunks/{velin-search-7B4KJ6TX.js → velin-search-B3L6J2RP.js} +2 -2
  134. package/dist/chunks/{velin-search-2XRQFBCS.js → velin-search-L3UG6NDQ.js} +5 -4
  135. package/dist/chunks/{velin-secure-field-6PV7RZDJ.js → velin-secure-field-DGYMP7OK.js} +1 -1
  136. package/dist/chunks/{velin-segmented-control-GYD5BIXQ.js → velin-segmented-control-P74GJPAR.js} +1 -1
  137. package/dist/chunks/{velin-sheet-R2Y67X6H.js → velin-sheet-M5GZZD7G.js} +2 -4
  138. package/dist/chunks/{velin-sheet-OUK6572T.js → velin-sheet-X7RXIWKV.js} +3 -5
  139. package/dist/chunks/{velin-stepper-X54WGHDG.js → velin-stepper-4YQJUHPC.js} +12 -5
  140. package/dist/chunks/{velin-toast-OMMOA2DK.js → velin-toast-UG5LWTG2.js} +5 -1
  141. package/dist/chunks/{velin-tooltip-BDHGRTQB.js → velin-tooltip-ZDH5SDLU.js} +1 -1
  142. package/dist/llms.txt +31 -8
  143. package/dist/search-index.json +182 -10
  144. package/dist/velin-agent.json +3980 -31
  145. package/dist/velinstyle-components.iife.js +1622 -286
  146. package/dist/velinstyle-components.js +1624 -286
  147. package/dist/velinstyle-components.min.js +262 -114
  148. package/dist/velinstyle.css +412 -67
  149. package/dist/velinstyle.d.ts +2 -0
  150. package/dist/velinstyle.min.css +1 -1
  151. package/package.json +21 -6
  152. package/packages/skill-engine/README.md +24 -0
  153. package/packages/skill-engine/package.json +7 -0
  154. package/packages/skill-engine/src/catalog.js +29 -0
  155. package/packages/skill-engine/src/index.js +5 -0
  156. package/packages/skill-engine/src/install.js +69 -0
  157. package/packages/skill-engine/src/registry.js +27 -0
  158. package/packages/skill-engine/src/resolve.js +68 -0
  159. package/packages/skill-engine/src/validate.js +40 -0
  160. package/packages/velinstyle-skills/README.md +6 -0
  161. package/packages/velinstyle-skills/adapter.json +8 -0
  162. package/packages/velinstyle-skills/bundles/landing-starter.bundle.yaml +12 -0
  163. package/packages/velinstyle-skills/bundles/review-suite.bundle.yaml +11 -0
  164. package/packages/velinstyle-skills/catalog.json +1004 -0
  165. package/packages/velinstyle-skills/graphs/component-ship.graph.yaml +14 -0
  166. package/packages/velinstyle-skills/graphs/landingpage.graph.yaml +21 -0
  167. package/packages/velinstyle-skills/graphs/release-gate.graph.yaml +15 -0
  168. package/packages/velinstyle-skills/index.js +22 -0
  169. package/packages/velinstyle-skills/package.json +7 -0
  170. package/packages/velinstyle-skills/packs/accessibility.pack.yaml +9 -0
  171. package/packages/velinstyle-skills/packs/design.pack.yaml +10 -0
  172. package/packages/velinstyle-skills/packs/documentation.pack.yaml +8 -0
  173. package/packages/velinstyle-skills/packs/enterprise.pack.yaml +10 -0
  174. package/packages/velinstyle-skills/packs/frontend.pack.yaml +10 -0
  175. package/packages/velinstyle-skills/packs/review.pack.yaml +9 -0
  176. package/packages/velinstyle-skills/projects/admin-panel.project.yaml +12 -0
  177. package/packages/velinstyle-skills/projects/blog.project.yaml +11 -0
  178. package/packages/velinstyle-skills/projects/documentation-portal.project.yaml +13 -0
  179. package/packages/velinstyle-skills/projects/ecommerce-shop.project.yaml +12 -0
  180. package/packages/velinstyle-skills/projects/landing-page.project.yaml +12 -0
  181. package/packages/velinstyle-skills/projects/laravel-dashboard.project.yaml +12 -0
  182. package/packages/velinstyle-skills/projects/marketing-website.project.yaml +14 -0
  183. package/packages/velinstyle-skills/projects/portfolio.project.yaml +12 -0
  184. package/packages/velinstyle-skills/registry.json +142 -0
  185. package/packages/velinstyle-skills/scripts/generate-assets.mjs +163 -0
  186. package/packages/velinstyle-skills/skills/velin-a11y-focus-keyboard/SKILL.md +57 -0
  187. package/packages/velinstyle-skills/skills/velin-a11y-page-checklist/SKILL.md +57 -0
  188. package/packages/velinstyle-skills/skills/velin-a11y-scan-fix/SKILL.md +57 -0
  189. package/packages/velinstyle-skills/skills/velin-ai-agent-briefing/SKILL.md +57 -0
  190. package/packages/velinstyle-skills/skills/velin-ai-plan-scaffold-review/SKILL.md +57 -0
  191. package/packages/velinstyle-skills/skills/velin-ai-skill-authoring/SKILL.md +57 -0
  192. package/packages/velinstyle-skills/skills/velin-components-accessibility-map/SKILL.md +57 -0
  193. package/packages/velinstyle-skills/skills/velin-components-api-contract/SKILL.md +57 -0
  194. package/packages/velinstyle-skills/skills/velin-components-recipe/SKILL.md +57 -0
  195. package/packages/velinstyle-skills/skills/velin-components-select-compose/SKILL.md +57 -0
  196. package/packages/velinstyle-skills/skills/velin-design-hero-compose/SKILL.md +57 -0
  197. package/packages/velinstyle-skills/skills/velin-design-section-rhythm/SKILL.md +57 -0
  198. package/packages/velinstyle-skills/skills/velin-design-surface-roles/SKILL.md +57 -0
  199. package/packages/velinstyle-skills/skills/velin-dev-component-wire/SKILL.md +57 -0
  200. package/packages/velinstyle-skills/skills/velin-dev-page-scaffold/SKILL.md +57 -0
  201. package/packages/velinstyle-skills/skills/velin-dev-plan-first/SKILL.md +57 -0
  202. package/packages/velinstyle-skills/skills/velin-docs-component-guide/SKILL.md +57 -0
  203. package/packages/velinstyle-skills/skills/velin-docs-generate-api/SKILL.md +57 -0
  204. package/packages/velinstyle-skills/skills/velin-dx-doctor-setup/SKILL.md +57 -0
  205. package/packages/velinstyle-skills/skills/velin-dx-project-init/SKILL.md +57 -0
  206. package/packages/velinstyle-skills/skills/velin-migration-legacy-wc/SKILL.md +57 -0
  207. package/packages/velinstyle-skills/skills/velin-migration-prefix-classes/SKILL.md +57 -0
  208. package/packages/velinstyle-skills/skills/velin-motion-reduced-safe/SKILL.md +57 -0
  209. package/packages/velinstyle-skills/skills/velin-motion-reveal-feedback/SKILL.md +57 -0
  210. package/packages/velinstyle-skills/skills/velin-perf-audit-fix/SKILL.md +57 -0
  211. package/packages/velinstyle-skills/skills/velin-perf-runtime-tree-shake/SKILL.md +57 -0
  212. package/packages/velinstyle-skills/skills/velin-release-changelog-sync/SKILL.md +57 -0
  213. package/packages/velinstyle-skills/skills/velin-release-meta-rebuild/SKILL.md +57 -0
  214. package/packages/velinstyle-skills/skills/velin-review-conversion-hero/SKILL.md +57 -0
  215. package/packages/velinstyle-skills/skills/velin-review-page-gate/SKILL.md +57 -0
  216. package/packages/velinstyle-skills/skills/velin-review-seo-meta/SKILL.md +57 -0
  217. package/packages/velinstyle-skills/skills/velin-security-sanitize-html/SKILL.md +57 -0
  218. package/packages/velinstyle-skills/skills/velin-security-scan-pii/SKILL.md +57 -0
  219. package/packages/velinstyle-skills/skills/velin-testing-a11y-suite/SKILL.md +57 -0
  220. package/packages/velinstyle-skills/skills/velin-testing-visual-smoke/SKILL.md +57 -0
  221. package/packages/velinstyle-skills/skills/velin-themes-apply-token/SKILL.md +57 -0
  222. package/packages/velinstyle-skills/skills/velin-themes-contrast-check/SKILL.md +57 -0
  223. package/packages/velinstyle-skills/skills/velin-utilities-layout-apply/SKILL.md +57 -0
  224. package/packages/velinstyle-skills/skills/velin-utilities-prefix-fix/SKILL.md +57 -0
  225. package/packages/velinstyle-skills/skills/velin-utilities-token-map/SKILL.md +57 -0
  226. package/packages/velinstyle-skills/templates/admin-panel.template.yaml +12 -0
  227. package/packages/velinstyle-skills/templates/blog.template.yaml +12 -0
  228. package/packages/velinstyle-skills/templates/documentation-portal.template.yaml +12 -0
  229. package/packages/velinstyle-skills/templates/ecommerce-shop.template.yaml +13 -0
  230. package/packages/velinstyle-skills/templates/landing-page.template.yaml +12 -0
  231. package/packages/velinstyle-skills/templates/laravel-dashboard.template.yaml +11 -0
  232. package/packages/velinstyle-skills/templates/marketing-website.template.yaml +13 -0
  233. package/packages/velinstyle-skills/templates/portfolio.template.yaml +12 -0
  234. package/schemas/component-knowledge.schema.json +33 -0
  235. package/schemas/design-constraint.schema.json +15 -0
  236. package/schemas/design-intelligence.schema.json +19 -0
  237. package/schemas/design-rule.schema.json +19 -0
  238. package/schemas/page-template.schema.json +24 -0
  239. package/schemas/review-report.schema.json +36 -0
  240. package/schemas/section.schema.json +22 -0
  241. package/schemas/skill-bundle.schema.json +15 -0
  242. package/schemas/skill-graph.schema.json +25 -0
  243. package/schemas/skill-pack.schema.json +14 -0
  244. package/schemas/skill-project.schema.json +16 -0
  245. package/schemas/skill-record.schema.json +27 -0
  246. package/schemas/skill-registry.schema.json +17 -0
  247. package/schemas/skill-template.schema.json +17 -0
  248. package/schemas/token-graph.schema.json +27 -0
  249. package/schemas/utility.schema.json +166 -0
  250. package/src/components/alert.css +22 -1
  251. package/src/components/calendar-dropzone.css +5 -0
  252. package/src/components/transparency.css +138 -0
  253. package/src/layout/app-shell.css +33 -0
  254. package/src/tokens/shadow.css +13 -0
  255. package/src/utilities/border.css +2 -0
  256. package/src/utilities/display.css +1 -24
  257. package/src/utilities/responsive.css +16 -1
  258. package/src/utilities/spacing.css +32 -0
  259. package/src/velinstyle.css +3 -0
  260. package/dist/chunks/attributes-3BZLI7XF.js +0 -364
  261. package/dist/chunks/attributes-4N5JP4CG.js +0 -364
  262. package/dist/chunks/attributes-5Q2WXGRC.js +0 -374
  263. package/dist/chunks/attributes-AIR7SVLK.js +0 -364
  264. package/dist/chunks/attributes-BGRN5XZO.js +0 -364
  265. package/dist/chunks/attributes-BVSQAYLR.js +0 -364
  266. package/dist/chunks/attributes-CDYFUY7Y.js +0 -364
  267. package/dist/chunks/attributes-JMYJZBPE.js +0 -364
  268. package/dist/chunks/attributes-R5JY3X4O.js +0 -374
  269. package/dist/chunks/attributes-TNSPQTHX.js +0 -374
  270. package/dist/chunks/chunk-2354NEBP.js +0 -109
  271. package/dist/chunks/chunk-2VNA7G7S.js +0 -109
  272. package/dist/chunks/chunk-AQLRJSGG.js +0 -109
  273. package/dist/chunks/chunk-EWPSDMQT.js +0 -109
  274. package/dist/chunks/chunk-LA7264K4.js +0 -85
  275. package/dist/chunks/chunk-QTJJ3DPO.js +0 -109
  276. package/dist/chunks/chunk-RZQVWFHW.js +0 -109
  277. package/dist/chunks/chunk-U4XHMZ7D.js +0 -109
  278. package/dist/chunks/chunk-V5YIUA6G.js +0 -109
  279. package/dist/chunks/chunk-XIET2VSZ.js +0 -109
  280. package/dist/chunks/chunk-XYLJ2GCB.js +0 -205
  281. package/dist/chunks/chunk-ZPSPKUYD.js +0 -109
  282. package/dist/chunks/highlight-XTHRKBA3.js +0 -37
  283. package/dist/chunks/velin-bottom-nav-2N2TYWOF.js +0 -86
  284. package/dist/chunks/velin-carousel-Y5VCOABZ.js +0 -213
  285. package/dist/chunks/velin-code-block-ASUBTAQV.js +0 -119
  286. package/dist/chunks/velin-code-block-TSUKPY4C.js +0 -123
  287. package/dist/chunks/velin-code-block-Y6CM726Q.js +0 -119
  288. package/dist/chunks/velin-combobox-2KDTCQ7N.js +0 -155
  289. package/dist/chunks/velin-command-M7RNHUPR.js +0 -136
  290. package/dist/chunks/velin-copy-T5KDTDXP.js +0 -81
  291. package/dist/chunks/velin-countdown-5XSTN3BH.js +0 -101
  292. package/dist/chunks/velin-counter-ISCTEAHI.js +0 -118
  293. package/dist/chunks/velin-dialog-D2GUHSCD.js +0 -144
  294. package/dist/chunks/velin-dialog-IJLFDXAJ.js +0 -144
  295. package/dist/chunks/velin-dialog-TNS3WXMB.js +0 -144
  296. package/dist/chunks/velin-drawer-MJS6WCF7.js +0 -130
  297. package/dist/chunks/velin-email-N5B5ZYTE.js +0 -90
  298. package/dist/chunks/velin-icon-KZO3IEHG.js +0 -164
  299. package/dist/chunks/velin-lightbox-I75U6JF4.js +0 -140
  300. package/dist/chunks/velin-lightbox-QOTB4PRL.js +0 -140
  301. package/dist/chunks/velin-lightbox-UCD6N7HF.js +0 -140
  302. package/dist/chunks/velin-live-dot-XHUZCIDZ.js +0 -67
  303. package/dist/chunks/velin-menubar-SFEXJE56.js +0 -86
  304. package/dist/chunks/velin-modal-2HOBXE6F.js +0 -176
  305. package/dist/chunks/velin-modal-GLI2XZZB.js +0 -176
  306. package/dist/chunks/velin-popover-EXINRIGJ.js +0 -145
  307. package/dist/chunks/velin-popover-OXX7MRZ6.js +0 -145
  308. package/dist/chunks/velin-popover-YKCCROJG.js +0 -145
  309. package/dist/chunks/velin-rating-XRQJV4LO.js +0 -91
  310. package/dist/chunks/velin-scroll-top-F2FCZNYD.js +0 -58
  311. package/dist/chunks/velin-search-4YHJWYSS.js +0 -556
  312. package/dist/chunks/velin-search-LWHY23Q5.js +0 -474
  313. package/dist/chunks/velin-secure-field-H7FSBUJW.js +0 -95
  314. package/dist/chunks/velin-segmented-control-PQX6LKOJ.js +0 -109
  315. package/dist/chunks/velin-sheet-3OGI4HD7.js +0 -119
  316. package/dist/chunks/velin-sparkline-GVEANJVW.js +0 -184
  317. package/dist/chunks/velin-sparkline-KDA3GQAN.js +0 -162
  318. package/dist/chunks/velin-stepper-2ZIHLKGM.js +0 -141
  319. package/dist/chunks/velin-stepper-FYEUEWE6.js +0 -141
  320. package/dist/chunks/velin-stepper-wc-QU3KRVQR.js +0 -133
  321. package/dist/chunks/velin-theme-toggle-BNNS7WLV.js +0 -285
  322. package/dist/chunks/velin-theme-toggle-NO7V4TWI.js +0 -285
  323. package/dist/chunks/velin-theme-toggle-QELCJM2Q.js +0 -291
  324. package/dist/chunks/velin-toast-RCZ4CSUC.js +0 -109
  325. package/dist/chunks/velin-toast-WEUBTJG6.js +0 -109
  326. package/dist/chunks/velin-tooltip-664IOHZA.js +0 -112
  327. package/dist/chunks/velin-tooltip-wc-LXDVT6DE.js +0 -103
  328. package/dist/chunks/worker-client-R6DBYPFT.js +0 -46
@@ -1,20 +1,24 @@
1
- const styles = `
2
- :host {
1
+ const LIGHT_STYLE_ID = 'velin-accordion-light-css';
2
+
3
+ /** Light-DOM styles: ::slotted() cannot target descendants of slotted <details>. */
4
+ const lightStyles = `
5
+ velin-accordion {
3
6
  display: block;
4
7
  border: 1px solid var(--velin-color-border, #ddd);
5
8
  border-radius: var(--velin-radius-md, 0.5rem);
6
9
  overflow: hidden;
7
10
  }
8
- ::slotted(details) {
11
+ velin-accordion details {
9
12
  border-bottom: 1px solid var(--velin-color-border, #ddd);
10
13
  }
11
- ::slotted(details:last-child) {
14
+ velin-accordion details:last-child {
12
15
  border-bottom: none;
13
16
  }
14
- ::slotted(details > summary) {
17
+ velin-accordion details > summary {
15
18
  display: flex;
16
19
  align-items: center;
17
20
  justify-content: space-between;
21
+ gap: var(--velin-space-3, 0.75rem);
18
22
  padding: var(--velin-space-4, 1rem);
19
23
  min-block-size: 2.75rem;
20
24
  font-size: var(--velin-text-base, 1rem);
@@ -23,16 +27,29 @@ const styles = `
23
27
  user-select: none;
24
28
  list-style: none;
25
29
  }
26
- ::slotted(details > summary::-webkit-details-marker) {
30
+ velin-accordion details > summary::-webkit-details-marker {
27
31
  display: none;
28
32
  }
29
- ::slotted(details[open] > summary) {
33
+ velin-accordion details > summary::after {
34
+ content: "";
35
+ flex-shrink: 0;
36
+ inline-size: 0.5rem;
37
+ block-size: 0.5rem;
38
+ border-inline-end: 2px solid currentColor;
39
+ border-block-end: 2px solid currentColor;
40
+ transform: rotate(45deg);
41
+ transition: transform 150ms ease;
42
+ }
43
+ velin-accordion details[open] > summary {
30
44
  background: var(--velin-color-primary-subtle, #eff6ff);
31
45
  color: var(--velin-color-primary, #2563eb);
32
46
  }
33
- ::slotted(details > :not(summary)) {
47
+ velin-accordion details[open] > summary::after {
48
+ transform: rotate(225deg);
49
+ }
50
+ velin-accordion details > :not(summary) {
34
51
  padding: var(--velin-space-4, 1rem) var(--velin-space-5, 1.25rem);
35
- background: var(--velin-color-bg-subtle, #f8fafc);
52
+ background: var(--velin-color-surface-dim, var(--velin-color-bg-subtle, #f8fafc));
36
53
  color: var(--velin-color-text-muted, #64748b);
37
54
  font-size: var(--velin-text-sm, 0.875rem);
38
55
  line-height: 1.6;
@@ -40,16 +57,33 @@ const styles = `
40
57
  }
41
58
  `;
42
59
 
60
+ const shadowStyles = `
61
+ :host {
62
+ display: block;
63
+ }
64
+ `;
65
+
66
+ function ensureLightStyles() {
67
+ if (typeof document === 'undefined') return;
68
+ if (document.getElementById(LIGHT_STYLE_ID)) return;
69
+ const style = document.createElement('style');
70
+ style.id = LIGHT_STYLE_ID;
71
+ style.textContent = lightStyles;
72
+ document.head.appendChild(style);
73
+ }
74
+
43
75
  class VelinAccordion extends HTMLElement {
44
76
  constructor() {
45
77
  super();
46
78
  this.attachShadow({ mode: 'open' });
47
79
  this._onToggle = this._onToggle.bind(this);
80
+ this._onKeydown = this._onKeydown.bind(this);
48
81
  }
49
82
 
50
83
  connectedCallback() {
84
+ ensureLightStyles();
51
85
  this.shadowRoot.innerHTML = `
52
- <style>${styles}</style>
86
+ <style>${shadowStyles}</style>
53
87
  <slot></slot>
54
88
  `;
55
89
 
@@ -57,7 +91,7 @@ class VelinAccordion extends HTMLElement {
57
91
  this._wireDetails();
58
92
 
59
93
  this.addEventListener('toggle', this._onToggle, true);
60
- this.addEventListener('keydown', this._onKeydown.bind(this));
94
+ this.addEventListener('keydown', this._onKeydown);
61
95
  }
62
96
 
63
97
  _wireDetails() {
@@ -69,14 +103,24 @@ class VelinAccordion extends HTMLElement {
69
103
  if (panel && !panel.id) panel.id = panelId;
70
104
  if (summary && panel) {
71
105
  summary.setAttribute('aria-controls', panelId);
106
+ summary.setAttribute('aria-expanded', details.open ? 'true' : 'false');
107
+ }
108
+ if (summary && !summary.hasAttribute('tabindex')) {
109
+ summary.setAttribute('tabindex', '0');
72
110
  }
73
111
  }
74
112
  }
75
113
 
76
114
  _onToggle(event) {
77
- if (!this._exclusive) return;
78
115
  const openedDetail = event.target;
79
- if (!openedDetail.open) return;
116
+ if (!(openedDetail instanceof HTMLDetailsElement)) return;
117
+
118
+ const summary = openedDetail.querySelector('summary');
119
+ if (summary) {
120
+ summary.setAttribute('aria-expanded', openedDetail.open ? 'true' : 'false');
121
+ }
122
+
123
+ if (!this._exclusive || !openedDetail.open) return;
80
124
 
81
125
  const details = [...this.querySelectorAll('details')];
82
126
  details.forEach((d) => {
@@ -109,6 +153,10 @@ class VelinAccordion extends HTMLElement {
109
153
  event.preventDefault();
110
154
  nextIndex = summaries.length - 1;
111
155
  break;
156
+ case 'Enter':
157
+ case ' ':
158
+ // Native summary already toggles on Enter/Space; don't double-handle.
159
+ return;
112
160
  default:
113
161
  return;
114
162
  }
@@ -117,6 +165,7 @@ class VelinAccordion extends HTMLElement {
117
165
 
118
166
  disconnectedCallback() {
119
167
  this.removeEventListener('toggle', this._onToggle, true);
168
+ this.removeEventListener('keydown', this._onKeydown);
120
169
  }
121
170
  }
122
171
 
@@ -69,6 +69,16 @@ class VelinBottomNav extends HTMLElement {
69
69
  }
70
70
  if (el.tagName === 'A' && !el.getAttribute('href')) {
71
71
  el.setAttribute('role', 'button');
72
+ if (!el.hasAttribute('tabindex')) el.setAttribute('tabindex', '0');
73
+ if (!el._velinBottomNavKey) {
74
+ el._velinBottomNavKey = (e) => {
75
+ if (e.key === 'Enter' || e.key === ' ') {
76
+ e.preventDefault();
77
+ el.click();
78
+ }
79
+ };
80
+ el.addEventListener('keydown', el._velinBottomNavKey);
81
+ }
72
82
  }
73
83
  });
74
84
  }
@@ -0,0 +1,212 @@
1
+ import { escapeHTML } from './sanitize.js';
2
+
3
+ const styles = `
4
+ :host { display: block; max-inline-size: 100%; }
5
+ .cal {
6
+ box-sizing: border-box;
7
+ border: 1px solid var(--velin-color-border, #ddd);
8
+ border-radius: var(--velin-radius-md, 0.5rem);
9
+ background: var(--velin-color-surface, #fff);
10
+ color: var(--velin-color-text, #111);
11
+ padding: var(--velin-space-3, 0.75rem);
12
+ max-inline-size: min(20rem, 100%);
13
+ inline-size: 100%;
14
+ }
15
+ .head {
16
+ display: flex; align-items: center; justify-content: space-between;
17
+ gap: var(--velin-space-2, 0.5rem); margin-block-end: var(--velin-space-3, 0.75rem);
18
+ }
19
+ .title { font-weight: var(--velin-weight-semibold, 600); margin: 0; font-size: var(--velin-text-base, 1rem); }
20
+ .nav {
21
+ display: inline-flex; align-items: center; justify-content: center;
22
+ flex-shrink: 0;
23
+ min-inline-size: 2.5rem; min-block-size: 2.5rem;
24
+ border: 1px solid var(--velin-color-border, #ddd);
25
+ border-radius: var(--velin-radius-sm, 0.25rem);
26
+ background: var(--velin-color-surface-bright, #fff);
27
+ color: inherit; cursor: pointer;
28
+ }
29
+ .nav:focus-visible { outline: 2px solid var(--velin-color-focus, #2563eb); outline-offset: 2px; }
30
+ .grid {
31
+ display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 0.25rem;
32
+ }
33
+ .dow {
34
+ text-align: center; font-size: var(--velin-text-xs, 0.75rem);
35
+ color: var(--velin-color-text-muted, #64748b); padding-block: 0.25rem;
36
+ }
37
+ .day {
38
+ inline-size: 100%;
39
+ min-inline-size: 0;
40
+ min-block-size: 2.25rem;
41
+ aspect-ratio: 1;
42
+ border: none; border-radius: var(--velin-radius-sm, 0.25rem);
43
+ background: transparent; color: inherit; cursor: pointer;
44
+ font: inherit;
45
+ padding: 0;
46
+ }
47
+ .day[aria-disabled="true"] { opacity: 0.35; cursor: not-allowed; }
48
+ .day[aria-selected="true"] {
49
+ background: var(--velin-color-primary, #2563eb);
50
+ color: var(--velin-color-on-primary, #fff);
51
+ }
52
+ .day:not([aria-disabled="true"]):hover {
53
+ background: var(--velin-color-primary-subtle, #eff6ff);
54
+ }
55
+ .day:focus-visible { outline: 2px solid var(--velin-color-focus, #2563eb); outline-offset: 1px; }
56
+ .out { color: var(--velin-color-text-muted, #94a3b8); }
57
+ `;
58
+
59
+ function iso(d) {
60
+ const y = d.getFullYear();
61
+ const m = String(d.getMonth() + 1).padStart(2, '0');
62
+ const day = String(d.getDate()).padStart(2, '0');
63
+ return `${y}-${m}-${day}`;
64
+ }
65
+
66
+ function parseISO(v) {
67
+ if (!v) return null;
68
+ const m = String(v).match(/^(\d{4})-(\d{2})-(\d{2})$/);
69
+ if (!m) return null;
70
+ const d = new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
71
+ return Number.isNaN(d.getTime()) ? null : d;
72
+ }
73
+
74
+ class VelinCalendar extends HTMLElement {
75
+ static get observedAttributes() {
76
+ return ['value', 'min', 'max', 'label'];
77
+ }
78
+
79
+ constructor() {
80
+ super();
81
+ this.attachShadow({ mode: 'open' });
82
+ this._view = new Date();
83
+ this._view.setDate(1);
84
+ this._onKey = this._onKey.bind(this);
85
+ }
86
+
87
+ connectedCallback() {
88
+ const selected = parseISO(this.getAttribute('value')) || new Date();
89
+ this._view = new Date(selected.getFullYear(), selected.getMonth(), 1);
90
+ this._render();
91
+ }
92
+
93
+ attributeChangedCallback(name, prev, next) {
94
+ if (prev === next || !this.shadowRoot?.querySelector('.cal')) return;
95
+ if (name === 'value' && next) {
96
+ const d = parseISO(next);
97
+ if (d) this._view = new Date(d.getFullYear(), d.getMonth(), 1);
98
+ }
99
+ this._render();
100
+ }
101
+
102
+ get value() {
103
+ return this.getAttribute('value') || '';
104
+ }
105
+
106
+ set value(v) {
107
+ if (v) this.setAttribute('value', v);
108
+ else this.removeAttribute('value');
109
+ }
110
+
111
+ _inRange(d) {
112
+ const min = parseISO(this.getAttribute('min'));
113
+ const max = parseISO(this.getAttribute('max'));
114
+ if (min && d < min) return false;
115
+ if (max && d > max) return false;
116
+ return true;
117
+ }
118
+
119
+ _select(d) {
120
+ if (!this._inRange(d)) return;
121
+ const v = iso(d);
122
+ this.setAttribute('value', v);
123
+ this.dispatchEvent(new CustomEvent('velin-change', { bubbles: true, detail: { value: v, date: d } }));
124
+ this._render();
125
+ }
126
+
127
+ _shiftMonth(delta) {
128
+ this._view = new Date(this._view.getFullYear(), this._view.getMonth() + delta, 1);
129
+ this._render();
130
+ }
131
+
132
+ _onKey(e) {
133
+ const selected = parseISO(this.getAttribute('value')) || new Date();
134
+ let next = new Date(selected);
135
+ switch (e.key) {
136
+ case 'ArrowLeft': next.setDate(next.getDate() - 1); break;
137
+ case 'ArrowRight': next.setDate(next.getDate() + 1); break;
138
+ case 'ArrowUp': next.setDate(next.getDate() - 7); break;
139
+ case 'ArrowDown': next.setDate(next.getDate() + 7); break;
140
+ case 'Home': next = new Date(next.getFullYear(), next.getMonth(), 1); break;
141
+ case 'End': next = new Date(next.getFullYear(), next.getMonth() + 1, 0); break;
142
+ case 'PageUp': next = new Date(next.getFullYear(), next.getMonth() - 1, next.getDate()); break;
143
+ case 'PageDown': next = new Date(next.getFullYear(), next.getMonth() + 1, next.getDate()); break;
144
+ case 'Enter':
145
+ case ' ':
146
+ e.preventDefault();
147
+ this._select(selected);
148
+ return;
149
+ default:
150
+ return;
151
+ }
152
+ e.preventDefault();
153
+ if (!this._inRange(next)) return;
154
+ this._view = new Date(next.getFullYear(), next.getMonth(), 1);
155
+ this.setAttribute('value', iso(next));
156
+ this.dispatchEvent(new CustomEvent('velin-change', { bubbles: true, detail: { value: iso(next), date: next } }));
157
+ this._render();
158
+ this.shadowRoot.querySelector(`[data-iso="${iso(next)}"]`)?.focus();
159
+ }
160
+
161
+ _render() {
162
+ const label = escapeHTML(this.getAttribute('label') || 'Choose date');
163
+ const selected = parseISO(this.getAttribute('value'));
164
+ const y = this._view.getFullYear();
165
+ const m = this._view.getMonth();
166
+ const title = this._view.toLocaleString(undefined, { month: 'long', year: 'numeric' });
167
+ const start = new Date(y, m, 1);
168
+ const startDow = (start.getDay() + 6) % 7; // Monday-first
169
+ const daysInMonth = new Date(y, m + 1, 0).getDate();
170
+ const dows = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'];
171
+
172
+ let cells = dows.map((d) => `<div class="dow" aria-hidden="true">${d}</div>`).join('');
173
+ for (let i = 0; i < startDow; i += 1) {
174
+ const d = new Date(y, m, -startDow + i + 1);
175
+ cells += `<button type="button" class="day out" tabindex="-1" data-iso="${iso(d)}" aria-label="${iso(d)}">${d.getDate()}</button>`;
176
+ }
177
+ for (let day = 1; day <= daysInMonth; day += 1) {
178
+ const d = new Date(y, m, day);
179
+ const id = iso(d);
180
+ const sel = selected && iso(selected) === id;
181
+ const disabled = !this._inRange(d);
182
+ cells += `<button type="button" class="day" data-iso="${id}" aria-label="${id}" aria-selected="${sel ? 'true' : 'false'}" aria-disabled="${disabled ? 'true' : 'false'}" tabindex="${sel ? '0' : '-1'}">${day}</button>`;
183
+ }
184
+
185
+ this.shadowRoot.innerHTML = `
186
+ <style>${styles}</style>
187
+ <div class="cal" role="group" aria-label="${label}">
188
+ <div class="head">
189
+ <button type="button" class="nav" data-nav="-1" aria-label="Previous month">‹</button>
190
+ <p class="title" id="cal-title">${escapeHTML(title)}</p>
191
+ <button type="button" class="nav" data-nav="1" aria-label="Next month">›</button>
192
+ </div>
193
+ <div class="grid" role="grid" aria-labelledby="cal-title">${cells}</div>
194
+ </div>
195
+ `;
196
+
197
+ this.shadowRoot.querySelectorAll('[data-nav]').forEach((btn) => {
198
+ btn.addEventListener('click', () => this._shiftMonth(Number(btn.getAttribute('data-nav'))));
199
+ });
200
+ this.shadowRoot.querySelectorAll('.day').forEach((btn) => {
201
+ btn.addEventListener('click', () => {
202
+ if (btn.getAttribute('aria-disabled') === 'true') return;
203
+ const d = parseISO(btn.getAttribute('data-iso'));
204
+ if (d) this._select(d);
205
+ });
206
+ btn.addEventListener('keydown', this._onKey);
207
+ });
208
+ }
209
+ }
210
+
211
+ customElements.define('velin-calendar', VelinCalendar);
212
+ export default VelinCalendar;
@@ -11,9 +11,14 @@ const styles = `
11
11
  padding: 10vh var(--velin-space-4, 1rem) var(--velin-space-4, 1rem);
12
12
  background: var(--velin-color-overlay, rgba(0,0,0,0.4));
13
13
  opacity: 0; visibility: hidden;
14
+ pointer-events: none;
14
15
  transition: opacity 150ms ease, visibility 150ms ease;
15
16
  }
16
- :host([open]) .overlay { opacity: 1; visibility: visible; }
17
+ :host([open]) .overlay {
18
+ opacity: 1;
19
+ visibility: visible;
20
+ pointer-events: auto;
21
+ }
17
22
  .panel {
18
23
  inline-size: min(32rem, 100%);
19
24
  background: var(--velin-color-surface-bright, #fff);
@@ -66,6 +71,7 @@ class VelinCommand extends HTMLElement {
66
71
  </div>
67
72
  `;
68
73
  this.shadowRoot.querySelector('.search').addEventListener('input', this._onInput);
74
+ this.shadowRoot.querySelector('.overlay')?.addEventListener('click', this._onOverlayClick);
69
75
  this.shadowRoot.querySelector('slot')?.addEventListener('slotchange', () => this._filter(''));
70
76
  this._filter('');
71
77
  }
@@ -79,6 +85,14 @@ class VelinCommand extends HTMLElement {
79
85
  this.removeAttribute('open');
80
86
  this.dispatchEvent(new CustomEvent('velin-close', { bubbles: true }));
81
87
  }
88
+ toggle() {
89
+ if (this.hasAttribute('open')) this.close();
90
+ else this.open();
91
+ }
92
+
93
+ _onOverlayClick = (event) => {
94
+ if (event.target === event.currentTarget) this.close();
95
+ };
82
96
 
83
97
  _open() {
84
98
  this._prev = saveFocus();
@@ -92,7 +106,7 @@ class VelinCommand extends HTMLElement {
92
106
 
93
107
  _close() {
94
108
  document.removeEventListener('keydown', this._onKey);
95
- clearBackgroundInert();
109
+ clearBackgroundInert(this);
96
110
  restoreFocus(this._prev);
97
111
  const input = this.shadowRoot.querySelector('.search');
98
112
  if (input) input.value = '';
@@ -135,6 +149,8 @@ class VelinCommand extends HTMLElement {
135
149
 
136
150
  disconnectedCallback() {
137
151
  document.removeEventListener('keydown', this._onKey);
152
+ this.shadowRoot?.querySelector('.overlay')?.removeEventListener('click', this._onOverlayClick);
153
+ if (this.hasAttribute('open')) clearBackgroundInert(this);
138
154
  }
139
155
  }
140
156
 
@@ -29,7 +29,7 @@ function sortValue(cell, type) {
29
29
 
30
30
  class VelinDataTable extends HTMLElement {
31
31
  static get observedAttributes() {
32
- return ['page-size', 'filter-input', 'empty-text', 'label'];
32
+ return ['page-size', 'filter-input', 'empty-text', 'label', 'editable'];
33
33
  }
34
34
 
35
35
  constructor() {
@@ -180,6 +180,7 @@ class VelinDataTable extends HTMLElement {
180
180
 
181
181
  this._ensureAccessibleName();
182
182
  this._setupSorting();
183
+ this._setupEditable();
183
184
  this._bindFilterInput();
184
185
  this._render();
185
186
  }
@@ -246,6 +247,82 @@ class VelinDataTable extends HTMLElement {
246
247
  });
247
248
  }
248
249
 
250
+ /**
251
+ * Inline edit: double-click or Enter on focused cell with data-editable / host editable.
252
+ * Enter saves, Escape cancels. Dispatches velin-data-table-edit.
253
+ */
254
+ _setupEditable() {
255
+ if (!this.hasAttribute('editable') && !this.querySelector('[data-editable]')) return;
256
+ const body = this._table.tBodies[0];
257
+ if (!body || body.dataset.velinEditBound) return;
258
+ body.dataset.velinEditBound = 'true';
259
+
260
+ body.addEventListener('dblclick', (e) => {
261
+ const cell = e.target.closest('td');
262
+ if (!cell || !body.contains(cell)) return;
263
+ if (!this.hasAttribute('editable') && !cell.hasAttribute('data-editable')) return;
264
+ this._beginEdit(cell);
265
+ });
266
+
267
+ body.addEventListener('keydown', (e) => {
268
+ const cell = e.target.closest('td');
269
+ if (!cell || e.target !== cell) return;
270
+ if (e.key === 'Enter' || e.key === 'F2') {
271
+ if (!this.hasAttribute('editable') && !cell.hasAttribute('data-editable')) return;
272
+ e.preventDefault();
273
+ this._beginEdit(cell);
274
+ }
275
+ });
276
+
277
+ for (const cell of body.querySelectorAll('td[data-editable], td')) {
278
+ if (!this.hasAttribute('editable') && !cell.hasAttribute('data-editable')) continue;
279
+ if (!cell.hasAttribute('tabindex')) cell.setAttribute('tabindex', '0');
280
+ }
281
+ }
282
+
283
+ /** @param {HTMLTableCellElement} cell */
284
+ _beginEdit(cell) {
285
+ if (cell.querySelector('input')) return;
286
+ const previous = cell.textContent.trim();
287
+ const input = document.createElement('input');
288
+ input.className = 'velin-input velin-data-table__edit';
289
+ input.value = previous;
290
+ input.setAttribute('aria-label', 'Edit cell');
291
+ cell.textContent = '';
292
+ cell.appendChild(input);
293
+ input.focus();
294
+ input.select();
295
+
296
+ const commit = (save) => {
297
+ const next = save ? input.value.trim() : previous;
298
+ cell.textContent = next;
299
+ if (save && next !== previous) {
300
+ this.dispatchEvent(new CustomEvent('velin-data-table-edit', {
301
+ bubbles: true,
302
+ detail: {
303
+ cell,
304
+ row: cell.parentElement,
305
+ previous,
306
+ value: next,
307
+ columnIndex: cell.cellIndex,
308
+ },
309
+ }));
310
+ announce('Cell updated');
311
+ }
312
+ };
313
+
314
+ input.addEventListener('keydown', (e) => {
315
+ if (e.key === 'Enter') {
316
+ e.preventDefault();
317
+ commit(true);
318
+ } else if (e.key === 'Escape') {
319
+ e.preventDefault();
320
+ commit(false);
321
+ }
322
+ });
323
+ input.addEventListener('blur', () => commit(true));
324
+ }
325
+
249
326
  _syncSortState() {
250
327
  this._headers().forEach((header, index) => {
251
328
  if (this._sortType(header) === 'none') return;
@@ -150,7 +150,10 @@ class VelinDialog extends HTMLElement {
150
150
  }
151
151
  this._resolve(value);
152
152
  this._resolve = null;
153
- this.dispatchEvent(new CustomEvent('velin-dialog-close', { bubbles: true, detail: { value } }));
153
+ const detail = { value };
154
+ this.dispatchEvent(new CustomEvent('velin-close', { bubbles: true, detail }));
155
+ // Deprecated alias — remove after deprecation window (ADR 0012)
156
+ this.dispatchEvent(new CustomEvent('velin-dialog-close', { bubbles: true, detail }));
154
157
  }
155
158
  }
156
159
 
@@ -88,7 +88,6 @@ class VelinDrawer extends HTMLElement {
88
88
  this._prev = saveFocus();
89
89
  setBackgroundInert(this);
90
90
  document.addEventListener('keydown', this._onKey);
91
- document.body.style.overflow = 'hidden';
92
91
  requestAnimationFrame(() => {
93
92
  const f = getFocusableElements(this.shadowRoot);
94
93
  if (f.length) f[0].focus();
@@ -97,8 +96,7 @@ class VelinDrawer extends HTMLElement {
97
96
 
98
97
  _close() {
99
98
  document.removeEventListener('keydown', this._onKey);
100
- document.body.style.overflow = '';
101
- clearBackgroundInert();
99
+ clearBackgroundInert(this);
102
100
  restoreFocus(this._prev);
103
101
  }
104
102
 
@@ -109,7 +107,7 @@ class VelinDrawer extends HTMLElement {
109
107
 
110
108
  disconnectedCallback() {
111
109
  document.removeEventListener('keydown', this._onKey);
112
- document.body.style.overflow = '';
110
+ clearBackgroundInert(this);
113
111
  }
114
112
  }
115
113