@birdapi/velinstyle 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/README.de.md +87 -158
  2. package/README.md +188 -115
  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-a11y.js +4 -2
  27. package/cli/docgen/extract-attributes.js +126 -10
  28. package/cli/docgen/extract-cli.js +3 -2
  29. package/cli/docgen/extract-components.js +61 -2
  30. package/cli/docgen/extract-utilities.js +10 -10
  31. package/cli/doctor.js +119 -0
  32. package/cli/index.js +535 -46
  33. package/cli/meta.js +84 -1
  34. package/cli/perf-audit.js +15 -2
  35. package/cli/prompt-engine.js +243 -0
  36. package/cli/review.js +268 -0
  37. package/cli/scaffold.js +119 -4
  38. package/cli/scanner-rules-data.js +7 -0
  39. package/cli/scanner.js +357 -4
  40. package/cli/serve.js +81 -0
  41. package/cli/skills.js +223 -0
  42. package/cli/wc-api.js +89 -0
  43. package/cli/workflow.js +42 -0
  44. package/components/index.js +4 -0
  45. package/components/runtime/component-loaders.js +4 -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 +438 -0
  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-form-summary.js +348 -0
  55. package/components/velin-icon.js +22 -1
  56. package/components/velin-lightbox.js +5 -3
  57. package/components/velin-modal.js +2 -4
  58. package/components/velin-search.js +1 -1
  59. package/components/velin-sheet.js +2 -4
  60. package/core/a11y/component-contracts.json +35 -1
  61. package/core/highlight/languages/go.js +28 -0
  62. package/core/highlight/languages/python.js +29 -0
  63. package/core/highlight/languages/rust.js +32 -0
  64. package/core/highlight/languages/yaml.js +23 -0
  65. package/core/highlight/registry.js +13 -2
  66. package/core/meta/build.js +126 -6
  67. package/core/meta/design-constraints/contact.json +9 -0
  68. package/core/meta/design-constraints/faq.json +9 -0
  69. package/core/meta/design-constraints/hero.json +13 -0
  70. package/core/meta/knowledge/components.json +622 -0
  71. package/core/meta/knowledge/tokens.json +282 -0
  72. package/core/meta/pages/registry.json +294 -0
  73. package/core/meta/schema.js +3 -1
  74. package/core/meta/sections/registry.json +185 -0
  75. package/dist/chunks/{attributes-TPANLMLF.js → attributes-A423NX5J.js} +3 -3
  76. package/dist/chunks/{attributes-ADOKLKA7.js → attributes-F6UPIEVP.js} +2 -2
  77. package/dist/chunks/{attributes-STYCS3O5.js → attributes-GLYXGGAL.js} +3 -3
  78. package/dist/chunks/{attributes-5Q2WXGRC.js → attributes-UFTYOSAU.js} +20 -3
  79. package/dist/chunks/attributes-XGLXLR2T.js +391 -0
  80. package/dist/chunks/attributes-YF4NI2QS.js +391 -0
  81. package/dist/chunks/browser-AUABBYUK.js +1544 -0
  82. package/dist/chunks/{chunk-SRL6EWHP.js → chunk-2LSKX57P.js} +13 -11
  83. package/dist/chunks/{chunk-RSMRR27R.js → chunk-2TGCVDUL.js} +11 -9
  84. package/dist/chunks/{chunk-XIET2VSZ.js → chunk-5JWGUAPC.js} +17 -13
  85. package/dist/chunks/chunk-7YSO2OQ2.js +113 -0
  86. package/dist/chunks/{chunk-IEHKRARD.js → chunk-BHR3ZG6U.js} +10 -8
  87. package/dist/chunks/{chunk-J472ERN2.js → chunk-ERF5YVP4.js} +15 -4
  88. package/dist/chunks/{chunk-XYLJ2GCB.js → chunk-JMSIHEYX.js} +55 -7
  89. package/dist/chunks/{chunk-MKZP2TBH.js → chunk-L7ZGUU4D.js} +2 -2
  90. package/dist/chunks/chunk-TUGIPKW5.js +113 -0
  91. package/dist/chunks/go-HZ6XTFCK.js +31 -0
  92. package/dist/chunks/{highlight-GJHHV4KM.js → highlight-IBDX4XWS.js} +1 -1
  93. package/dist/chunks/{highlight-XTHRKBA3.js → highlight-M2ELQNYK.js} +1 -1
  94. package/dist/chunks/python-BMPKDKNO.js +32 -0
  95. package/dist/chunks/runtime-entry.js +1 -1
  96. package/dist/chunks/rust-2BWKI2MN.js +35 -0
  97. package/dist/chunks/{velin-accordion-FBIPAEXG.js → velin-accordion-WSY6BMLA.js} +64 -10
  98. package/dist/chunks/{velin-bottom-nav-7GEMPIM6.js → velin-bottom-nav-5RVRNGIP.js} +25 -0
  99. package/dist/chunks/{velin-bottom-nav-2N2TYWOF.js → velin-bottom-nav-N5F4UO2I.js} +26 -1
  100. package/dist/chunks/velin-calendar-OFE6THUD.js +210 -0
  101. package/dist/chunks/velin-calendar-PGVNJTXK.js +217 -0
  102. package/dist/chunks/velin-calendar-XC7JRDSH.js +217 -0
  103. package/dist/chunks/{velin-code-block-CIAURDRJ.js → velin-code-block-ITCLIC6T.js} +1 -1
  104. package/dist/chunks/{velin-code-block-TSUKPY4C.js → velin-code-block-ZGWG7JI5.js} +12 -3
  105. package/dist/chunks/{velin-combobox-NXS4QB4R.js → velin-combobox-56V2ZWT5.js} +1 -1
  106. package/dist/chunks/{velin-command-ONKO2A3J.js → velin-command-2HO2EKR6.js} +29 -2
  107. package/dist/chunks/{velin-command-TMLSRGIU.js → velin-command-ZJSLPK7B.js} +30 -3
  108. package/dist/chunks/{velin-copy-NYDBOKXT.js → velin-copy-XDQSV2XU.js} +1 -1
  109. package/dist/chunks/{velin-countdown-4ZVDGK4R.js → velin-countdown-V4Z5MA63.js} +1 -1
  110. package/dist/chunks/velin-data-table-KK7IDGTP.js +302 -0
  111. package/dist/chunks/velin-data-table-UVR42UUM.js +372 -0
  112. package/dist/chunks/{velin-dialog-GTTZI564.js → velin-dialog-3YK2RPRV.js} +9 -2
  113. package/dist/chunks/{velin-dialog-ELFOZIXZ.js → velin-dialog-S24KAP4S.js} +3 -1
  114. package/dist/chunks/{velin-drawer-BE6TYN3H.js → velin-drawer-5PNU624J.js} +2 -4
  115. package/dist/chunks/{velin-drawer-DLL2GLT6.js → velin-drawer-CCM6S25D.js} +3 -5
  116. package/dist/chunks/{velin-email-RBX6ZR4S.js → velin-email-TNFONXPW.js} +1 -1
  117. package/dist/chunks/velin-file-dropzone-QRGF2JNA.js +154 -0
  118. package/dist/chunks/velin-file-dropzone-XIZMJ3NB.js +154 -0
  119. package/dist/chunks/velin-form-summary-XRQ7COQH.js +273 -0
  120. package/dist/chunks/{velin-icon-7M76DOPB.js → velin-icon-A6NCXGUK.js} +59 -17
  121. package/dist/chunks/{velin-icon-ZTSKUOVN.js → velin-icon-EC4B5XCM.js} +18 -5
  122. package/dist/chunks/{velin-lightbox-6E7CAATP.js → velin-lightbox-FFK4TUUP.js} +7 -6
  123. package/dist/chunks/{velin-lightbox-I75U6JF4.js → velin-lightbox-P725FLTY.js} +15 -5
  124. package/dist/chunks/{velin-menubar-J66JXRWW.js → velin-menubar-6I2LM5HL.js} +1 -1
  125. package/dist/chunks/{velin-modal-5HYNNNUI.js → velin-modal-ICTMGRSU.js} +7 -8
  126. package/dist/chunks/{velin-modal-AEOTZ67O.js → velin-modal-JBNODH7D.js} +2 -4
  127. package/dist/chunks/{velin-popover-T72HK3DF.js → velin-popover-WZG2GHBL.js} +25 -4
  128. package/dist/chunks/{velin-rating-N4DI2XNL.js → velin-rating-QBBYRRBU.js} +1 -1
  129. package/dist/chunks/{velin-search-7B4KJ6TX.js → velin-search-B3L6J2RP.js} +2 -2
  130. package/dist/chunks/{velin-search-2XRQFBCS.js → velin-search-L3UG6NDQ.js} +5 -4
  131. package/dist/chunks/{velin-secure-field-6PV7RZDJ.js → velin-secure-field-DGYMP7OK.js} +1 -1
  132. package/dist/chunks/{velin-segmented-control-GYD5BIXQ.js → velin-segmented-control-P74GJPAR.js} +1 -1
  133. package/dist/chunks/{velin-sheet-R2Y67X6H.js → velin-sheet-M5GZZD7G.js} +2 -4
  134. package/dist/chunks/{velin-sheet-OUK6572T.js → velin-sheet-X7RXIWKV.js} +3 -5
  135. package/dist/chunks/{velin-stepper-X54WGHDG.js → velin-stepper-4YQJUHPC.js} +12 -5
  136. package/dist/chunks/{velin-toast-OMMOA2DK.js → velin-toast-UG5LWTG2.js} +5 -1
  137. package/dist/chunks/{velin-tooltip-BDHGRTQB.js → velin-tooltip-ZDH5SDLU.js} +1 -1
  138. package/dist/chunks/yaml-O67LEQYT.js +26 -0
  139. package/dist/llms.txt +29 -7
  140. package/dist/search-index.json +182 -10
  141. package/dist/velin-agent.json +3997 -26
  142. package/dist/velinstyle-components.iife.js +1952 -287
  143. package/dist/velinstyle-components.js +1956 -287
  144. package/dist/velinstyle-components.min.js +267 -119
  145. package/dist/velinstyle.css +381 -67
  146. package/dist/velinstyle.d.ts +4 -0
  147. package/dist/velinstyle.min.css +1 -1
  148. package/package.json +26 -6
  149. package/packages/skill-engine/README.md +24 -0
  150. package/packages/skill-engine/package.json +7 -0
  151. package/packages/skill-engine/src/catalog.js +29 -0
  152. package/packages/skill-engine/src/index.js +5 -0
  153. package/packages/skill-engine/src/install.js +69 -0
  154. package/packages/skill-engine/src/registry.js +27 -0
  155. package/packages/skill-engine/src/resolve.js +68 -0
  156. package/packages/skill-engine/src/validate.js +40 -0
  157. package/packages/velinstyle-skills/README.md +6 -0
  158. package/packages/velinstyle-skills/adapter.json +8 -0
  159. package/packages/velinstyle-skills/bundles/landing-starter.bundle.yaml +12 -0
  160. package/packages/velinstyle-skills/bundles/review-suite.bundle.yaml +11 -0
  161. package/packages/velinstyle-skills/catalog.json +1004 -0
  162. package/packages/velinstyle-skills/graphs/component-ship.graph.yaml +14 -0
  163. package/packages/velinstyle-skills/graphs/landingpage.graph.yaml +21 -0
  164. package/packages/velinstyle-skills/graphs/release-gate.graph.yaml +15 -0
  165. package/packages/velinstyle-skills/index.js +22 -0
  166. package/packages/velinstyle-skills/package.json +7 -0
  167. package/packages/velinstyle-skills/packs/accessibility.pack.yaml +9 -0
  168. package/packages/velinstyle-skills/packs/design.pack.yaml +10 -0
  169. package/packages/velinstyle-skills/packs/documentation.pack.yaml +8 -0
  170. package/packages/velinstyle-skills/packs/enterprise.pack.yaml +10 -0
  171. package/packages/velinstyle-skills/packs/frontend.pack.yaml +10 -0
  172. package/packages/velinstyle-skills/packs/review.pack.yaml +9 -0
  173. package/packages/velinstyle-skills/projects/admin-panel.project.yaml +12 -0
  174. package/packages/velinstyle-skills/projects/blog.project.yaml +11 -0
  175. package/packages/velinstyle-skills/projects/documentation-portal.project.yaml +13 -0
  176. package/packages/velinstyle-skills/projects/ecommerce-shop.project.yaml +12 -0
  177. package/packages/velinstyle-skills/projects/landing-page.project.yaml +12 -0
  178. package/packages/velinstyle-skills/projects/laravel-dashboard.project.yaml +12 -0
  179. package/packages/velinstyle-skills/projects/marketing-website.project.yaml +14 -0
  180. package/packages/velinstyle-skills/projects/portfolio.project.yaml +12 -0
  181. package/packages/velinstyle-skills/registry.json +142 -0
  182. package/packages/velinstyle-skills/scripts/generate-assets.mjs +163 -0
  183. package/packages/velinstyle-skills/skills/velin-a11y-focus-keyboard/SKILL.md +57 -0
  184. package/packages/velinstyle-skills/skills/velin-a11y-page-checklist/SKILL.md +57 -0
  185. package/packages/velinstyle-skills/skills/velin-a11y-scan-fix/SKILL.md +57 -0
  186. package/packages/velinstyle-skills/skills/velin-ai-agent-briefing/SKILL.md +57 -0
  187. package/packages/velinstyle-skills/skills/velin-ai-plan-scaffold-review/SKILL.md +57 -0
  188. package/packages/velinstyle-skills/skills/velin-ai-skill-authoring/SKILL.md +57 -0
  189. package/packages/velinstyle-skills/skills/velin-components-accessibility-map/SKILL.md +57 -0
  190. package/packages/velinstyle-skills/skills/velin-components-api-contract/SKILL.md +57 -0
  191. package/packages/velinstyle-skills/skills/velin-components-recipe/SKILL.md +57 -0
  192. package/packages/velinstyle-skills/skills/velin-components-select-compose/SKILL.md +57 -0
  193. package/packages/velinstyle-skills/skills/velin-design-hero-compose/SKILL.md +57 -0
  194. package/packages/velinstyle-skills/skills/velin-design-section-rhythm/SKILL.md +57 -0
  195. package/packages/velinstyle-skills/skills/velin-design-surface-roles/SKILL.md +57 -0
  196. package/packages/velinstyle-skills/skills/velin-dev-component-wire/SKILL.md +57 -0
  197. package/packages/velinstyle-skills/skills/velin-dev-page-scaffold/SKILL.md +57 -0
  198. package/packages/velinstyle-skills/skills/velin-dev-plan-first/SKILL.md +57 -0
  199. package/packages/velinstyle-skills/skills/velin-docs-component-guide/SKILL.md +57 -0
  200. package/packages/velinstyle-skills/skills/velin-docs-generate-api/SKILL.md +57 -0
  201. package/packages/velinstyle-skills/skills/velin-dx-doctor-setup/SKILL.md +57 -0
  202. package/packages/velinstyle-skills/skills/velin-dx-project-init/SKILL.md +57 -0
  203. package/packages/velinstyle-skills/skills/velin-migration-legacy-wc/SKILL.md +57 -0
  204. package/packages/velinstyle-skills/skills/velin-migration-prefix-classes/SKILL.md +57 -0
  205. package/packages/velinstyle-skills/skills/velin-motion-reduced-safe/SKILL.md +57 -0
  206. package/packages/velinstyle-skills/skills/velin-motion-reveal-feedback/SKILL.md +57 -0
  207. package/packages/velinstyle-skills/skills/velin-perf-audit-fix/SKILL.md +57 -0
  208. package/packages/velinstyle-skills/skills/velin-perf-runtime-tree-shake/SKILL.md +57 -0
  209. package/packages/velinstyle-skills/skills/velin-release-changelog-sync/SKILL.md +57 -0
  210. package/packages/velinstyle-skills/skills/velin-release-meta-rebuild/SKILL.md +57 -0
  211. package/packages/velinstyle-skills/skills/velin-review-conversion-hero/SKILL.md +57 -0
  212. package/packages/velinstyle-skills/skills/velin-review-page-gate/SKILL.md +57 -0
  213. package/packages/velinstyle-skills/skills/velin-review-seo-meta/SKILL.md +57 -0
  214. package/packages/velinstyle-skills/skills/velin-security-sanitize-html/SKILL.md +57 -0
  215. package/packages/velinstyle-skills/skills/velin-security-scan-pii/SKILL.md +57 -0
  216. package/packages/velinstyle-skills/skills/velin-testing-a11y-suite/SKILL.md +57 -0
  217. package/packages/velinstyle-skills/skills/velin-testing-visual-smoke/SKILL.md +57 -0
  218. package/packages/velinstyle-skills/skills/velin-themes-apply-token/SKILL.md +57 -0
  219. package/packages/velinstyle-skills/skills/velin-themes-contrast-check/SKILL.md +57 -0
  220. package/packages/velinstyle-skills/skills/velin-utilities-layout-apply/SKILL.md +57 -0
  221. package/packages/velinstyle-skills/skills/velin-utilities-prefix-fix/SKILL.md +57 -0
  222. package/packages/velinstyle-skills/skills/velin-utilities-token-map/SKILL.md +57 -0
  223. package/packages/velinstyle-skills/templates/admin-panel.template.yaml +12 -0
  224. package/packages/velinstyle-skills/templates/blog.template.yaml +12 -0
  225. package/packages/velinstyle-skills/templates/documentation-portal.template.yaml +12 -0
  226. package/packages/velinstyle-skills/templates/ecommerce-shop.template.yaml +13 -0
  227. package/packages/velinstyle-skills/templates/landing-page.template.yaml +12 -0
  228. package/packages/velinstyle-skills/templates/laravel-dashboard.template.yaml +11 -0
  229. package/packages/velinstyle-skills/templates/marketing-website.template.yaml +13 -0
  230. package/packages/velinstyle-skills/templates/portfolio.template.yaml +12 -0
  231. package/schemas/component-knowledge.schema.json +33 -0
  232. package/schemas/design-constraint.schema.json +15 -0
  233. package/schemas/design-intelligence.schema.json +19 -0
  234. package/schemas/design-rule.schema.json +19 -0
  235. package/schemas/page-template.schema.json +24 -0
  236. package/schemas/review-report.schema.json +36 -0
  237. package/schemas/section.schema.json +22 -0
  238. package/schemas/skill-bundle.schema.json +15 -0
  239. package/schemas/skill-graph.schema.json +25 -0
  240. package/schemas/skill-pack.schema.json +14 -0
  241. package/schemas/skill-project.schema.json +16 -0
  242. package/schemas/skill-record.schema.json +27 -0
  243. package/schemas/skill-registry.schema.json +17 -0
  244. package/schemas/skill-template.schema.json +17 -0
  245. package/schemas/token-graph.schema.json +27 -0
  246. package/schemas/utility.schema.json +166 -0
  247. package/src/base/wc-placeholder.css +7 -0
  248. package/src/components/alert.css +22 -1
  249. package/src/components/calendar-dropzone.css +5 -0
  250. package/src/components/data-table.css +93 -0
  251. package/src/components/form-validation.css +40 -0
  252. package/src/layout/app-shell.css +33 -0
  253. package/src/tokens/shadow.css +13 -0
  254. package/src/utilities/border.css +2 -0
  255. package/src/utilities/display.css +1 -24
  256. package/src/utilities/responsive.css +16 -1
  257. package/src/utilities/spacing.css +32 -0
  258. package/src/velinstyle.css +3 -0
  259. package/dist/chunks/attributes-3BZLI7XF.js +0 -364
  260. package/dist/chunks/attributes-4N5JP4CG.js +0 -364
  261. package/dist/chunks/attributes-AIR7SVLK.js +0 -364
  262. package/dist/chunks/attributes-BGRN5XZO.js +0 -364
  263. package/dist/chunks/attributes-BVSQAYLR.js +0 -364
  264. package/dist/chunks/attributes-CDYFUY7Y.js +0 -364
  265. package/dist/chunks/attributes-JMYJZBPE.js +0 -364
  266. package/dist/chunks/attributes-R5JY3X4O.js +0 -374
  267. package/dist/chunks/attributes-TNSPQTHX.js +0 -374
  268. package/dist/chunks/chunk-2354NEBP.js +0 -109
  269. package/dist/chunks/chunk-2VNA7G7S.js +0 -109
  270. package/dist/chunks/chunk-AQLRJSGG.js +0 -109
  271. package/dist/chunks/chunk-EWPSDMQT.js +0 -109
  272. package/dist/chunks/chunk-LA7264K4.js +0 -85
  273. package/dist/chunks/chunk-QTJJ3DPO.js +0 -109
  274. package/dist/chunks/chunk-RZQVWFHW.js +0 -109
  275. package/dist/chunks/chunk-U4XHMZ7D.js +0 -109
  276. package/dist/chunks/chunk-V5YIUA6G.js +0 -109
  277. package/dist/chunks/chunk-ZPSPKUYD.js +0 -109
  278. package/dist/chunks/velin-bottom-nav-N3DFQR66.js +0 -86
  279. package/dist/chunks/velin-carousel-Y5VCOABZ.js +0 -213
  280. package/dist/chunks/velin-code-block-ASUBTAQV.js +0 -119
  281. package/dist/chunks/velin-code-block-Y6CM726Q.js +0 -119
  282. package/dist/chunks/velin-combobox-2KDTCQ7N.js +0 -155
  283. package/dist/chunks/velin-command-M7RNHUPR.js +0 -136
  284. package/dist/chunks/velin-copy-T5KDTDXP.js +0 -81
  285. package/dist/chunks/velin-countdown-5XSTN3BH.js +0 -101
  286. package/dist/chunks/velin-counter-ISCTEAHI.js +0 -118
  287. package/dist/chunks/velin-dialog-D2GUHSCD.js +0 -144
  288. package/dist/chunks/velin-dialog-IJLFDXAJ.js +0 -144
  289. package/dist/chunks/velin-dialog-TNS3WXMB.js +0 -144
  290. package/dist/chunks/velin-drawer-MJS6WCF7.js +0 -130
  291. package/dist/chunks/velin-email-N5B5ZYTE.js +0 -90
  292. package/dist/chunks/velin-icon-KZO3IEHG.js +0 -164
  293. package/dist/chunks/velin-lightbox-QOTB4PRL.js +0 -140
  294. package/dist/chunks/velin-lightbox-UCD6N7HF.js +0 -140
  295. package/dist/chunks/velin-live-dot-XHUZCIDZ.js +0 -67
  296. package/dist/chunks/velin-menubar-SFEXJE56.js +0 -86
  297. package/dist/chunks/velin-modal-2HOBXE6F.js +0 -176
  298. package/dist/chunks/velin-modal-GLI2XZZB.js +0 -176
  299. package/dist/chunks/velin-popover-EXINRIGJ.js +0 -145
  300. package/dist/chunks/velin-popover-OXX7MRZ6.js +0 -145
  301. package/dist/chunks/velin-popover-YKCCROJG.js +0 -145
  302. package/dist/chunks/velin-rating-XRQJV4LO.js +0 -91
  303. package/dist/chunks/velin-scroll-top-F2FCZNYD.js +0 -58
  304. package/dist/chunks/velin-search-4YHJWYSS.js +0 -556
  305. package/dist/chunks/velin-search-LWHY23Q5.js +0 -474
  306. package/dist/chunks/velin-secure-field-H7FSBUJW.js +0 -95
  307. package/dist/chunks/velin-segmented-control-PQX6LKOJ.js +0 -109
  308. package/dist/chunks/velin-sheet-3OGI4HD7.js +0 -119
  309. package/dist/chunks/velin-sparkline-GVEANJVW.js +0 -184
  310. package/dist/chunks/velin-sparkline-KDA3GQAN.js +0 -162
  311. package/dist/chunks/velin-stepper-2ZIHLKGM.js +0 -141
  312. package/dist/chunks/velin-stepper-FYEUEWE6.js +0 -141
  313. package/dist/chunks/velin-stepper-wc-QU3KRVQR.js +0 -133
  314. package/dist/chunks/velin-theme-toggle-BNNS7WLV.js +0 -285
  315. package/dist/chunks/velin-theme-toggle-NO7V4TWI.js +0 -285
  316. package/dist/chunks/velin-theme-toggle-QELCJM2Q.js +0 -291
  317. package/dist/chunks/velin-toast-RCZ4CSUC.js +0 -109
  318. package/dist/chunks/velin-toast-WEUBTJG6.js +0 -109
  319. package/dist/chunks/velin-tooltip-664IOHZA.js +0 -112
  320. package/dist/chunks/velin-tooltip-wc-LXDVT6DE.js +0 -103
  321. package/dist/chunks/worker-client-R6DBYPFT.js +0 -46
package/cli/serve.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Static file server for local previews.
3
+ */
4
+ import { createServer } from 'http';
5
+ import { readFileSync, existsSync, statSync } from 'fs';
6
+ import { join, resolve, extname, normalize } from 'path';
7
+
8
+ const MIME = {
9
+ '.html': 'text/html; charset=utf-8',
10
+ '.css': 'text/css; charset=utf-8',
11
+ '.js': 'text/javascript; charset=utf-8',
12
+ '.mjs': 'text/javascript; charset=utf-8',
13
+ '.json': 'application/json; charset=utf-8',
14
+ '.svg': 'image/svg+xml',
15
+ '.png': 'image/png',
16
+ '.jpg': 'image/jpeg',
17
+ '.jpeg': 'image/jpeg',
18
+ '.webp': 'image/webp',
19
+ '.woff2': 'font/woff2',
20
+ '.ico': 'image/x-icon',
21
+ '.map': 'application/json',
22
+ };
23
+
24
+ function safeJoin(root, reqPath) {
25
+ const decoded = decodeURIComponent((reqPath || '/').split('?')[0]);
26
+ const cleaned = normalize(decoded).replace(/^(\.\.[/\\])+/, '');
27
+ const full = resolve(root, '.' + (cleaned.startsWith('/') || cleaned.startsWith('\\') ? cleaned : `/${cleaned}`));
28
+ if (!full.startsWith(resolve(root))) return null;
29
+ return full;
30
+ }
31
+
32
+ /**
33
+ * @param {{ dir?: string, port?: number, host?: string }} opts
34
+ */
35
+ export function serveStatic(opts = {}) {
36
+ const dir = resolve(opts.dir || '.');
37
+ const port = Number(opts.port) || 4173;
38
+ const host = opts.host || '127.0.0.1';
39
+
40
+ if (!existsSync(dir) || !statSync(dir).isDirectory()) {
41
+ return { ok: false, error: `Not a directory: ${dir}` };
42
+ }
43
+
44
+ const server = createServer((req, res) => {
45
+ let filePath = safeJoin(dir, req.url || '/');
46
+ if (!filePath) {
47
+ res.writeHead(403);
48
+ res.end('Forbidden');
49
+ return;
50
+ }
51
+ if (existsSync(filePath) && statSync(filePath).isDirectory()) {
52
+ filePath = join(filePath, 'index.html');
53
+ }
54
+ if (!existsSync(filePath) || !statSync(filePath).isFile()) {
55
+ res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
56
+ res.end('Not found');
57
+ return;
58
+ }
59
+ const type = MIME[extname(filePath).toLowerCase()] || 'application/octet-stream';
60
+ try {
61
+ const body = readFileSync(filePath);
62
+ res.writeHead(200, { 'Content-Type': type });
63
+ res.end(body);
64
+ } catch {
65
+ res.writeHead(500);
66
+ res.end('Read error');
67
+ }
68
+ });
69
+
70
+ return new Promise((resolvePromise) => {
71
+ server.listen(port, host, () => {
72
+ resolvePromise({
73
+ ok: true,
74
+ server,
75
+ url: `http://${host}:${port}/`,
76
+ dir,
77
+ close: () => new Promise((r) => server.close(() => r())),
78
+ });
79
+ });
80
+ });
81
+ }
package/cli/skills.js ADDED
@@ -0,0 +1,223 @@
1
+ import { resolve, join, dirname } from 'path';
2
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
3
+ import { fileURLToPath } from 'url';
4
+ import {
5
+ loadRegistry,
6
+ listSkills,
7
+ findSkillById,
8
+ validateRegistry,
9
+ resolveSkillGraph,
10
+ installSelection,
11
+ } from '../packages/skill-engine/src/index.js';
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const PKG_ROOT = join(__dirname, '..');
15
+ const REGISTRY_PATH = join(PKG_ROOT, 'packages', 'velinstyle-skills', 'registry.json');
16
+ const SKILLS_ROOT = join(PKG_ROOT, 'packages', 'velinstyle-skills');
17
+
18
+ function argValue(argv, flag) {
19
+ const idx = argv.indexOf(flag);
20
+ return idx !== -1 ? argv[idx + 1] : null;
21
+ }
22
+
23
+ function hasFlag(argv, flag) {
24
+ return argv.includes(flag);
25
+ }
26
+
27
+ export function loadSkillRegistry() {
28
+ return loadRegistry(REGISTRY_PATH);
29
+ }
30
+
31
+ export function skillsList(argv = []) {
32
+ const registry = loadSkillRegistry();
33
+ const items = listSkills(registry, {
34
+ capability: argValue(argv, '--capability') || undefined,
35
+ status: argValue(argv, '--status') || undefined,
36
+ priority: argValue(argv, '--priority') || undefined,
37
+ origin: argValue(argv, '--origin') || undefined,
38
+ category: argValue(argv, '--category') || undefined,
39
+ });
40
+ if (hasFlag(argv, '--json')) {
41
+ console.log(JSON.stringify(items, null, 2));
42
+ return;
43
+ }
44
+ for (const item of items) {
45
+ console.log(`${item.id} [${item.category}] ${item.priority}/${item.status} capabilities=${(item.capabilities || []).join(',')}`);
46
+ }
47
+ console.log(`\n${items.length} skill(s)`);
48
+ }
49
+
50
+ export function skillsShow(skillId, argv = []) {
51
+ const registry = loadSkillRegistry();
52
+ const skill = findSkillById(registry, skillId);
53
+ if (!skill) {
54
+ console.error(`Unknown skill: ${skillId}`);
55
+ process.exit(1);
56
+ }
57
+ if (hasFlag(argv, '--human')) {
58
+ console.log(formatSkillHuman(skill));
59
+ return;
60
+ }
61
+ console.log(JSON.stringify(skill, null, 2));
62
+ }
63
+
64
+ function formatSkillHuman(skill) {
65
+ const lines = [
66
+ `# ${skill.id}`,
67
+ '',
68
+ skill.title ? `**${skill.title}**` : '',
69
+ skill.summary || skill.description || '',
70
+ '',
71
+ `- Category: ${skill.category || '—'}`,
72
+ `- Status: ${skill.status || '—'}`,
73
+ `- Priority: ${skill.priority || '—'}`,
74
+ `- Capabilities: ${(skill.capabilities || []).join(', ') || '—'}`,
75
+ ];
76
+ if (skill.requiresCli?.length) lines.push(`- CLI: ${skill.requiresCli.join(', ')}`);
77
+ if (skill.inputs?.length) {
78
+ lines.push('', '## Inputs');
79
+ for (const input of skill.inputs) {
80
+ if (typeof input === 'string') {
81
+ lines.push(`- \`${input}\``);
82
+ continue;
83
+ }
84
+ const label = input.name || input.id || input.key || input.type || JSON.stringify(input);
85
+ lines.push(`- \`${label}\`${input.required ? ' (required)' : ''}: ${input.description || input.type || ''}`.trim());
86
+ }
87
+ }
88
+ if (skill.outputs?.length) {
89
+ lines.push('', '## Outputs');
90
+ for (const output of skill.outputs) {
91
+ if (typeof output === 'string') {
92
+ lines.push(`- \`${output}\``);
93
+ continue;
94
+ }
95
+ const label = output.name || output.id || output.key || output.type || JSON.stringify(output);
96
+ lines.push(`- \`${label}\`: ${output.description || output.type || ''}`.trim());
97
+ }
98
+ }
99
+ if (skill.dependsOn?.length) {
100
+ lines.push('', `## Depends on`, skill.dependsOn.map((d) => `- ${d}`).join('\n'));
101
+ }
102
+ lines.push('', '_Tip: blueprints must only emit classes present in CSS (`velinstyle blueprint --strict`)._');
103
+ return lines.filter(Boolean).join('\n');
104
+ }
105
+
106
+ export function skillsInstall(argv = []) {
107
+ const selection = argv[0];
108
+ if (!selection) {
109
+ console.error('Usage: velinstyle skills install <skill-id|pack|bundle:id|project:id>');
110
+ process.exit(1);
111
+ }
112
+ const target = resolve(argValue(argv, '--target') || '.cursor/skills');
113
+ mkdirSync(target, { recursive: true });
114
+ const registry = loadSkillRegistry();
115
+ const result = installSelection(registry, {
116
+ selection,
117
+ skillsRoot: SKILLS_ROOT,
118
+ targetRoot: target,
119
+ includeDependencies: !hasFlag(argv, '--no-deps'),
120
+ });
121
+ for (const installed of result.installed) console.log(`Installed ${installed}`);
122
+ if (result.issues.length) {
123
+ for (const issue of result.issues) console.warn(`Warning: ${issue}`);
124
+ }
125
+ const markerPath = join(target, 'registry-source.json');
126
+ writeFileSync(markerPath, JSON.stringify({ source: REGISTRY_PATH, installed: result.installed }, null, 2), 'utf-8');
127
+ }
128
+
129
+ export function skillsRun(skillId, argv = []) {
130
+ const registry = loadSkillRegistry();
131
+ const resolved = resolveSkillGraph(registry, skillId);
132
+ if (resolved.issues.length) {
133
+ for (const issue of resolved.issues) console.error(issue);
134
+ process.exit(1);
135
+ }
136
+ const steps = [];
137
+ for (const id of resolved.orderedSkillIds) {
138
+ const skill = findSkillById(registry, id);
139
+ if (!skill) continue;
140
+ steps.push({ id: skill.id, requiresCli: skill.requiresCli || [], onlyIf: skill.onlyIf || [] });
141
+ }
142
+ if (hasFlag(argv, '--json')) {
143
+ console.log(JSON.stringify({ steps }, null, 2));
144
+ return;
145
+ }
146
+ for (const step of steps) {
147
+ console.log(`- ${step.id}`);
148
+ if (step.requiresCli.length) console.log(` cli: ${step.requiresCli.join(', ')}`);
149
+ if (step.onlyIf.length) console.log(` onlyIf: ${step.onlyIf.join(', ')}`);
150
+ }
151
+ }
152
+
153
+ export function skillsValidate() {
154
+ const registry = loadSkillRegistry();
155
+ const result = validateRegistry(registry);
156
+ if (result.errors.length) {
157
+ for (const error of result.errors) console.error(`Error: ${error}`);
158
+ }
159
+ if (result.warnings.length) {
160
+ for (const warning of result.warnings) console.warn(`Warning: ${warning}`);
161
+ }
162
+ console.log(result.ok ? 'skills registry valid' : 'skills registry invalid');
163
+ process.exit(result.ok ? 0 : 1);
164
+ }
165
+
166
+ export async function skillsDoctor(argv = []) {
167
+ const { doctorSkillPaths } = await import('../scripts/check-skills-paths.mjs');
168
+ const result = doctorSkillPaths(PKG_ROOT);
169
+ if (hasFlag(argv, '--json')) {
170
+ console.log(JSON.stringify(result, null, 2));
171
+ process.exit(result.ok ? 0 : 1);
172
+ }
173
+ if (!result.ok) {
174
+ console.error(`skills doctor FAILED (${result.errors.length} missing path(s)):`);
175
+ for (const e of result.errors) console.error(` - ${e}`);
176
+ process.exit(1);
177
+ }
178
+ console.log(`skills doctor OK (${result.checked} paths).`);
179
+ }
180
+
181
+ export function skillsIndex(kind) {
182
+ const registry = loadSkillRegistry();
183
+ const map = {
184
+ packs: registry.packs || [],
185
+ bundles: registry.bundles || [],
186
+ templates: registry.templates || [],
187
+ projects: registry.projects || [],
188
+ graphs: registry.workflowGraphs || [],
189
+ };
190
+ const out = map[kind] || [];
191
+ console.log(JSON.stringify(out, null, 2));
192
+ }
193
+
194
+ export function skillsCommand(argv = []) {
195
+ const sub = argv[0];
196
+ if (!sub || sub === '--help' || sub === '-h') {
197
+ console.log(`Usage: velinstyle skills <subcommand>
198
+
199
+ Subcommands:
200
+ list [--category <id>] [--status <id>] [--json]
201
+ show <skill-id> [--human]
202
+ install <skill-id|pack:id|bundle:id|template:id>
203
+ run <skill-id> [--json] (dry-run / inspect — not apply)
204
+ validate
205
+ doctor [--json] Fail if demo/docs/starter paths missing
206
+ packs | bundles | templates | projects | graphs
207
+ `);
208
+ process.exit(0);
209
+ }
210
+ if (sub === 'list') return skillsList(argv.slice(1));
211
+ if (sub === 'show') return skillsShow(argv[1], argv.slice(2));
212
+ if (sub === 'install') return skillsInstall(argv.slice(1));
213
+ if (sub === 'run') return skillsRun(argv[1], argv.slice(2));
214
+ if (sub === 'validate') return skillsValidate();
215
+ if (sub === 'doctor') return skillsDoctor(argv.slice(1));
216
+ if (sub === 'packs' || sub === 'bundles' || sub === 'templates' || sub === 'projects' || sub === 'graphs') return skillsIndex(sub);
217
+ console.error(`Unknown skills subcommand: ${sub}`);
218
+ process.exit(1);
219
+ }
220
+
221
+ export function getRegistryPathForMeta() {
222
+ return REGISTRY_PATH;
223
+ }
package/cli/wc-api.js ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Human-readable WC API from source + generated docs tip.
3
+ */
4
+ import { existsSync, readFileSync } from 'fs';
5
+ import { join } from 'path';
6
+
7
+ /**
8
+ * @param {string} pkgRoot
9
+ * @param {string} tag
10
+ */
11
+ export function describeWcApi(pkgRoot, tag) {
12
+ const name = String(tag || '').replace(/^</, '').replace(/>$/, '').trim();
13
+ if (!name.startsWith('velin-')) {
14
+ return { ok: false, error: `Expected a velin-* tag (got "${tag || ''}"). Example: velinstyle wc api velin-toast` };
15
+ }
16
+ const file = join(pkgRoot, 'components', `${name}.js`);
17
+ if (!existsSync(file)) {
18
+ return { ok: false, error: `No source at components/${name}.js` };
19
+ }
20
+ const src = readFileSync(file, 'utf-8');
21
+ const attrs = [...src.matchAll(/static\s+get\s+observedAttributes\(\)\s*\{\s*return\s*\[([^\]]*)\]/gs)]
22
+ .map((m) => m[1].split(',').map((s) => s.replace(/['"`\s]/g, '')).filter(Boolean))
23
+ .flat();
24
+ const methods = [...src.matchAll(/^\s{2}([a-zA-Z_][\w]*)\s*\([^)]*\)\s*\{/gm)]
25
+ .map((m) => m[1])
26
+ .filter((n) => !['constructor', 'connectedCallback', 'disconnectedCallback', 'attributeChangedCallback', 'adoptedCallback'].includes(n));
27
+ const showSig = src.match(/show\s*\(\s*\{([^}]*)\}\s*=\s*\{\s*\}\s*\)/);
28
+ const events = [...src.matchAll(/new\s+CustomEvent\(\s*['"]([^'"]+)['"]/g)].map((m) => m[1]);
29
+ const unique = (arr) => [...new Set(arr)];
30
+
31
+ const docPath = join(pkgRoot, 'docs/generated/components', `${name}.md`);
32
+ const hasDoc = existsSync(docPath);
33
+
34
+ let example = '';
35
+ if (name === 'velin-toast' && showSig) {
36
+ example = `<velin-toast></velin-toast>
37
+ <script type="module">
38
+ const t = document.querySelector('velin-toast');
39
+ t.show({ message: 'Saved', type: 'success', duration: 4000 });
40
+ </script>`;
41
+ } else if (name === 'velin-calendar') {
42
+ example = `<velin-calendar label="Pick a day" value="2026-07-30"></velin-calendar>`;
43
+ } else if (name === 'velin-file-dropzone') {
44
+ example = `<velin-file-dropzone label="Files" accept=".pdf,.png" multiple></velin-file-dropzone>`;
45
+ } else if (name === 'velin-data-table') {
46
+ example = `<velin-data-table label="Rows" page-size="5" filter-input="#q" editable>
47
+ <table>…</table>
48
+ </velin-data-table>`;
49
+ }
50
+
51
+ return {
52
+ ok: true,
53
+ tag: name,
54
+ source: `components/${name}.js`,
55
+ observedAttributes: unique(attrs),
56
+ methods: unique(methods),
57
+ events: unique(events),
58
+ showSignature: showSig ? `show({ ${showSig[1].trim()} } = {})` : null,
59
+ generatedDoc: hasDoc ? `docs/generated/components/${name}.md` : null,
60
+ example: example || null,
61
+ };
62
+ }
63
+
64
+ export function formatWcApi(report) {
65
+ if (!report.ok) return report.error;
66
+ const lines = [
67
+ `# <${report.tag}>`,
68
+ '',
69
+ `Source: \`${report.source}\``,
70
+ report.generatedDoc ? `Generated docs: \`${report.generatedDoc}\`` : 'Generated docs: (missing — run `velinstyle docs generate`)',
71
+ '',
72
+ '## observedAttributes',
73
+ report.observedAttributes.length ? report.observedAttributes.map((a) => `- \`${a}\``).join('\n') : '_none_',
74
+ '',
75
+ '## Methods (from source)',
76
+ report.methods.length ? report.methods.map((m) => `- \`${m}()\``).join('\n') : '_none detected_',
77
+ ];
78
+ if (report.showSignature) {
79
+ lines.push('', '## Toast show()', `\`${report.showSignature}\``);
80
+ }
81
+ if (report.events.length) {
82
+ lines.push('', '## Custom events', report.events.map((e) => `- \`${e}\``).join('\n'));
83
+ }
84
+ if (report.example) {
85
+ lines.push('', '## Example', '```html', report.example, '```');
86
+ }
87
+ lines.push('', '_Tip: offline create projects include `vendor/velinstyle/docs/` mini copies of core WC markdown._');
88
+ return lines.join('\n');
89
+ }
@@ -0,0 +1,42 @@
1
+ import { loadRegistry, resolveWorkflowGraph } from '../packages/skill-engine/src/index.js';
2
+ import { getRegistryPathForMeta } from './skills.js';
3
+
4
+ function hasFlag(argv, flag) {
5
+ return argv.includes(flag);
6
+ }
7
+
8
+ export function workflowCommand(argv = []) {
9
+ const workflowId = argv[0];
10
+ if (!workflowId || workflowId === '--help' || workflowId === '-h') {
11
+ console.log(`Usage: velinstyle workflow <graph-id|project:id> [--json]
12
+
13
+ Examples:
14
+ velinstyle workflow landingpage
15
+ velinstyle workflow project:marketing-site --json
16
+ `);
17
+ process.exit(0);
18
+ }
19
+ const registry = loadRegistry(getRegistryPathForMeta());
20
+ let resolved;
21
+ if (workflowId.startsWith('project:')) {
22
+ const projectId = workflowId.replace('project:', '');
23
+ const project = (registry.projects || []).find((item) => item.id === projectId);
24
+ if (!project) {
25
+ console.error(`Unknown project: ${projectId}`);
26
+ process.exit(1);
27
+ }
28
+ resolved = resolveWorkflowGraph(registry, project.workflowGraph);
29
+ } else {
30
+ resolved = resolveWorkflowGraph(registry, workflowId);
31
+ }
32
+ if (resolved.issues.length) {
33
+ for (const issue of resolved.issues) console.error(issue);
34
+ process.exit(1);
35
+ }
36
+ if (hasFlag(argv, '--json')) {
37
+ console.log(JSON.stringify(resolved, null, 2));
38
+ return;
39
+ }
40
+ console.log(`Workflow steps (${resolved.orderedSteps.length}):`);
41
+ for (const step of resolved.orderedSteps) console.log(`- ${step}`);
42
+ }
@@ -33,6 +33,10 @@ export { default as VelinSparkline } from './velin-sparkline.js';
33
33
  export { default as VelinCounter } from './velin-counter.js';
34
34
  export { default as VelinLiveDot } from './velin-live-dot.js';
35
35
  export { default as VelinCodeBlock } from './velin-code-block.js';
36
+ export { default as VelinDataTable } from './velin-data-table.js';
37
+ export { default as VelinFormSummary } from './velin-form-summary.js';
38
+ export { default as VelinCalendar } from './velin-calendar.js';
39
+ export { default as VelinFileDropzone } from './velin-file-dropzone.js';
36
40
  export { default as VelinSearch } from './velin-search.js';
37
41
  export { bindDeclarativeSearch } from './velin-search.js';
38
42
  export { initReveal, initMotion, velinMotion } from './velin-reveal.js';
@@ -5,6 +5,7 @@ export const COMPONENT_LOADERS = {
5
5
  'velin-accordion': () => import('../velin-accordion.js'),
6
6
  'velin-announcer': () => import('../velin-announcer.js'),
7
7
  'velin-bottom-nav': () => import('../velin-bottom-nav.js'),
8
+ 'velin-calendar': () => import('../velin-calendar.js'),
8
9
  'velin-carousel': () => import('../velin-carousel.js'),
9
10
  'velin-code-block': () => import('../velin-code-block.js'),
10
11
  'velin-collapse': () => import('../velin-collapse.js'),
@@ -13,10 +14,13 @@ export const COMPONENT_LOADERS = {
13
14
  'velin-copy': () => import('../velin-copy.js'),
14
15
  'velin-countdown': () => import('../velin-countdown.js'),
15
16
  'velin-counter': () => import('../velin-counter.js'),
17
+ 'velin-data-table': () => import('../velin-data-table.js'),
16
18
  'velin-dialog': () => import('../velin-dialog.js'),
17
19
  'velin-drawer': () => import('../velin-drawer.js'),
18
20
  'velin-dropdown': () => import('../velin-dropdown.js'),
19
21
  'velin-email': () => import('../velin-email.js'),
22
+ 'velin-file-dropzone': () => import('../velin-file-dropzone.js'),
23
+ 'velin-form-summary': () => import('../velin-form-summary.js'),
20
24
  'velin-icon': () => import('../velin-icon.js'),
21
25
  'velin-lightbox': () => import('../velin-lightbox.js'),
22
26
  'velin-live-dot': () => import('../velin-live-dot.js'),
@@ -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
  }