@birdapi/velinstyle 1.1.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 (308) hide show
  1. package/README.de.md +87 -162
  2. package/README.md +188 -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 +126 -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 +531 -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/wc-api.js +89 -0
  42. package/cli/workflow.js +42 -0
  43. package/components/index.js +2 -0
  44. package/components/runtime/component-loaders.js +2 -0
  45. package/components/velin-accordion.js +62 -13
  46. package/components/velin-bottom-nav.js +10 -0
  47. package/components/velin-calendar.js +212 -0
  48. package/components/velin-command.js +18 -2
  49. package/components/velin-data-table.js +78 -1
  50. package/components/velin-dialog.js +4 -1
  51. package/components/velin-drawer.js +2 -4
  52. package/components/velin-file-dropzone.js +162 -0
  53. package/components/velin-icon.js +22 -1
  54. package/components/velin-lightbox.js +5 -3
  55. package/components/velin-modal.js +2 -4
  56. package/components/velin-search.js +1 -1
  57. package/components/velin-sheet.js +2 -4
  58. package/core/a11y/component-contracts.json +20 -3
  59. package/core/meta/build.js +125 -5
  60. package/core/meta/design-constraints/contact.json +9 -0
  61. package/core/meta/design-constraints/faq.json +9 -0
  62. package/core/meta/design-constraints/hero.json +13 -0
  63. package/core/meta/knowledge/components.json +622 -0
  64. package/core/meta/knowledge/tokens.json +282 -0
  65. package/core/meta/pages/registry.json +294 -0
  66. package/core/meta/schema.js +3 -1
  67. package/core/meta/sections/registry.json +185 -0
  68. package/dist/chunks/{attributes-STYCS3O5.js → attributes-A423NX5J.js} +3 -3
  69. package/dist/chunks/{attributes-353XDOAX.js → attributes-F6UPIEVP.js} +1 -1
  70. package/dist/chunks/{attributes-ADOKLKA7.js → attributes-GLYXGGAL.js} +3 -3
  71. package/dist/chunks/{attributes-TPANLMLF.js → attributes-UFTYOSAU.js} +3 -3
  72. package/dist/chunks/attributes-XGLXLR2T.js +391 -0
  73. package/dist/chunks/attributes-YF4NI2QS.js +391 -0
  74. package/dist/chunks/browser-AUABBYUK.js +1544 -0
  75. package/dist/chunks/{chunk-RSMRR27R.js → chunk-2LSKX57P.js} +12 -10
  76. package/dist/chunks/{chunk-IEHKRARD.js → chunk-2TGCVDUL.js} +11 -9
  77. package/dist/chunks/{chunk-SRL6EWHP.js → chunk-5JWGUAPC.js} +17 -13
  78. package/dist/chunks/chunk-7YSO2OQ2.js +113 -0
  79. package/dist/chunks/{chunk-QVHYL3R4.js → chunk-BHR3ZG6U.js} +6 -6
  80. package/dist/chunks/{chunk-J472ERN2.js → chunk-JMSIHEYX.js} +15 -4
  81. package/dist/chunks/{chunk-MKZP2TBH.js → chunk-L7ZGUU4D.js} +2 -2
  82. package/dist/chunks/chunk-TUGIPKW5.js +113 -0
  83. package/dist/chunks/{highlight-GJHHV4KM.js → highlight-M2ELQNYK.js} +1 -1
  84. package/dist/chunks/runtime-entry.js +1 -1
  85. package/dist/chunks/{velin-accordion-FBIPAEXG.js → velin-accordion-WSY6BMLA.js} +64 -10
  86. package/dist/chunks/{velin-bottom-nav-7GEMPIM6.js → velin-bottom-nav-5RVRNGIP.js} +25 -0
  87. package/dist/chunks/{velin-bottom-nav-N3DFQR66.js → velin-bottom-nav-N5F4UO2I.js} +26 -1
  88. package/dist/chunks/velin-calendar-OFE6THUD.js +210 -0
  89. package/dist/chunks/velin-calendar-PGVNJTXK.js +217 -0
  90. package/dist/chunks/velin-calendar-XC7JRDSH.js +217 -0
  91. package/dist/chunks/{velin-code-block-CIAURDRJ.js → velin-code-block-ZGWG7JI5.js} +1 -1
  92. package/dist/chunks/{velin-combobox-NXS4QB4R.js → velin-combobox-56V2ZWT5.js} +1 -1
  93. package/dist/chunks/{velin-command-ONKO2A3J.js → velin-command-2HO2EKR6.js} +29 -2
  94. package/dist/chunks/{velin-command-TMLSRGIU.js → velin-command-ZJSLPK7B.js} +30 -3
  95. package/dist/chunks/{velin-copy-NYDBOKXT.js → velin-copy-XDQSV2XU.js} +1 -1
  96. package/dist/chunks/{velin-countdown-4ZVDGK4R.js → velin-countdown-V4Z5MA63.js} +1 -1
  97. package/dist/chunks/velin-data-table-UVR42UUM.js +372 -0
  98. package/dist/chunks/{velin-dialog-GTTZI564.js → velin-dialog-3YK2RPRV.js} +9 -2
  99. package/dist/chunks/{velin-dialog-ELFOZIXZ.js → velin-dialog-S24KAP4S.js} +3 -1
  100. package/dist/chunks/{velin-drawer-BE6TYN3H.js → velin-drawer-5PNU624J.js} +2 -4
  101. package/dist/chunks/{velin-drawer-DLL2GLT6.js → velin-drawer-CCM6S25D.js} +3 -5
  102. package/dist/chunks/{velin-email-RBX6ZR4S.js → velin-email-TNFONXPW.js} +1 -1
  103. package/dist/chunks/velin-file-dropzone-QRGF2JNA.js +154 -0
  104. package/dist/chunks/velin-file-dropzone-XIZMJ3NB.js +154 -0
  105. package/dist/chunks/{velin-icon-7M76DOPB.js → velin-icon-A6NCXGUK.js} +59 -17
  106. package/dist/chunks/{velin-icon-ZTSKUOVN.js → velin-icon-EC4B5XCM.js} +18 -5
  107. package/dist/chunks/{velin-lightbox-6E7CAATP.js → velin-lightbox-FFK4TUUP.js} +7 -6
  108. package/dist/chunks/{velin-lightbox-NXA3U2FM.js → velin-lightbox-P725FLTY.js} +5 -4
  109. package/dist/chunks/{velin-menubar-J66JXRWW.js → velin-menubar-6I2LM5HL.js} +1 -1
  110. package/dist/chunks/{velin-modal-5HYNNNUI.js → velin-modal-ICTMGRSU.js} +7 -8
  111. package/dist/chunks/{velin-modal-AEOTZ67O.js → velin-modal-JBNODH7D.js} +2 -4
  112. package/dist/chunks/{velin-popover-T72HK3DF.js → velin-popover-WZG2GHBL.js} +25 -4
  113. package/dist/chunks/{velin-rating-N4DI2XNL.js → velin-rating-QBBYRRBU.js} +1 -1
  114. package/dist/chunks/{velin-search-7B4KJ6TX.js → velin-search-B3L6J2RP.js} +2 -2
  115. package/dist/chunks/{velin-search-2XRQFBCS.js → velin-search-L3UG6NDQ.js} +5 -4
  116. package/dist/chunks/{velin-secure-field-6PV7RZDJ.js → velin-secure-field-DGYMP7OK.js} +1 -1
  117. package/dist/chunks/{velin-segmented-control-GYD5BIXQ.js → velin-segmented-control-P74GJPAR.js} +1 -1
  118. package/dist/chunks/{velin-sheet-R2Y67X6H.js → velin-sheet-M5GZZD7G.js} +2 -4
  119. package/dist/chunks/{velin-sheet-OUK6572T.js → velin-sheet-X7RXIWKV.js} +3 -5
  120. package/dist/chunks/{velin-stepper-X54WGHDG.js → velin-stepper-4YQJUHPC.js} +12 -5
  121. package/dist/chunks/{velin-toast-OMMOA2DK.js → velin-toast-UG5LWTG2.js} +5 -1
  122. package/dist/chunks/{velin-tooltip-BDHGRTQB.js → velin-tooltip-ZDH5SDLU.js} +1 -1
  123. package/dist/llms.txt +29 -7
  124. package/dist/search-index.json +156 -10
  125. package/dist/velin-agent.json +3973 -28
  126. package/dist/velinstyle-components.iife.js +1211 -284
  127. package/dist/velinstyle-components.js +1213 -284
  128. package/dist/velinstyle-components.min.js +266 -118
  129. package/dist/velinstyle.css +252 -67
  130. package/dist/velinstyle.d.ts +2 -0
  131. package/dist/velinstyle.min.css +1 -1
  132. package/package.json +20 -6
  133. package/packages/skill-engine/README.md +24 -0
  134. package/packages/skill-engine/package.json +7 -0
  135. package/packages/skill-engine/src/catalog.js +29 -0
  136. package/packages/skill-engine/src/index.js +5 -0
  137. package/packages/skill-engine/src/install.js +69 -0
  138. package/packages/skill-engine/src/registry.js +27 -0
  139. package/packages/skill-engine/src/resolve.js +68 -0
  140. package/packages/skill-engine/src/validate.js +40 -0
  141. package/packages/velinstyle-skills/README.md +6 -0
  142. package/packages/velinstyle-skills/adapter.json +8 -0
  143. package/packages/velinstyle-skills/bundles/landing-starter.bundle.yaml +12 -0
  144. package/packages/velinstyle-skills/bundles/review-suite.bundle.yaml +11 -0
  145. package/packages/velinstyle-skills/catalog.json +1004 -0
  146. package/packages/velinstyle-skills/graphs/component-ship.graph.yaml +14 -0
  147. package/packages/velinstyle-skills/graphs/landingpage.graph.yaml +21 -0
  148. package/packages/velinstyle-skills/graphs/release-gate.graph.yaml +15 -0
  149. package/packages/velinstyle-skills/index.js +22 -0
  150. package/packages/velinstyle-skills/package.json +7 -0
  151. package/packages/velinstyle-skills/packs/accessibility.pack.yaml +9 -0
  152. package/packages/velinstyle-skills/packs/design.pack.yaml +10 -0
  153. package/packages/velinstyle-skills/packs/documentation.pack.yaml +8 -0
  154. package/packages/velinstyle-skills/packs/enterprise.pack.yaml +10 -0
  155. package/packages/velinstyle-skills/packs/frontend.pack.yaml +10 -0
  156. package/packages/velinstyle-skills/packs/review.pack.yaml +9 -0
  157. package/packages/velinstyle-skills/projects/admin-panel.project.yaml +12 -0
  158. package/packages/velinstyle-skills/projects/blog.project.yaml +11 -0
  159. package/packages/velinstyle-skills/projects/documentation-portal.project.yaml +13 -0
  160. package/packages/velinstyle-skills/projects/ecommerce-shop.project.yaml +12 -0
  161. package/packages/velinstyle-skills/projects/landing-page.project.yaml +12 -0
  162. package/packages/velinstyle-skills/projects/laravel-dashboard.project.yaml +12 -0
  163. package/packages/velinstyle-skills/projects/marketing-website.project.yaml +14 -0
  164. package/packages/velinstyle-skills/projects/portfolio.project.yaml +12 -0
  165. package/packages/velinstyle-skills/registry.json +142 -0
  166. package/packages/velinstyle-skills/scripts/generate-assets.mjs +163 -0
  167. package/packages/velinstyle-skills/skills/velin-a11y-focus-keyboard/SKILL.md +57 -0
  168. package/packages/velinstyle-skills/skills/velin-a11y-page-checklist/SKILL.md +57 -0
  169. package/packages/velinstyle-skills/skills/velin-a11y-scan-fix/SKILL.md +57 -0
  170. package/packages/velinstyle-skills/skills/velin-ai-agent-briefing/SKILL.md +57 -0
  171. package/packages/velinstyle-skills/skills/velin-ai-plan-scaffold-review/SKILL.md +57 -0
  172. package/packages/velinstyle-skills/skills/velin-ai-skill-authoring/SKILL.md +57 -0
  173. package/packages/velinstyle-skills/skills/velin-components-accessibility-map/SKILL.md +57 -0
  174. package/packages/velinstyle-skills/skills/velin-components-api-contract/SKILL.md +57 -0
  175. package/packages/velinstyle-skills/skills/velin-components-recipe/SKILL.md +57 -0
  176. package/packages/velinstyle-skills/skills/velin-components-select-compose/SKILL.md +57 -0
  177. package/packages/velinstyle-skills/skills/velin-design-hero-compose/SKILL.md +57 -0
  178. package/packages/velinstyle-skills/skills/velin-design-section-rhythm/SKILL.md +57 -0
  179. package/packages/velinstyle-skills/skills/velin-design-surface-roles/SKILL.md +57 -0
  180. package/packages/velinstyle-skills/skills/velin-dev-component-wire/SKILL.md +57 -0
  181. package/packages/velinstyle-skills/skills/velin-dev-page-scaffold/SKILL.md +57 -0
  182. package/packages/velinstyle-skills/skills/velin-dev-plan-first/SKILL.md +57 -0
  183. package/packages/velinstyle-skills/skills/velin-docs-component-guide/SKILL.md +57 -0
  184. package/packages/velinstyle-skills/skills/velin-docs-generate-api/SKILL.md +57 -0
  185. package/packages/velinstyle-skills/skills/velin-dx-doctor-setup/SKILL.md +57 -0
  186. package/packages/velinstyle-skills/skills/velin-dx-project-init/SKILL.md +57 -0
  187. package/packages/velinstyle-skills/skills/velin-migration-legacy-wc/SKILL.md +57 -0
  188. package/packages/velinstyle-skills/skills/velin-migration-prefix-classes/SKILL.md +57 -0
  189. package/packages/velinstyle-skills/skills/velin-motion-reduced-safe/SKILL.md +57 -0
  190. package/packages/velinstyle-skills/skills/velin-motion-reveal-feedback/SKILL.md +57 -0
  191. package/packages/velinstyle-skills/skills/velin-perf-audit-fix/SKILL.md +57 -0
  192. package/packages/velinstyle-skills/skills/velin-perf-runtime-tree-shake/SKILL.md +57 -0
  193. package/packages/velinstyle-skills/skills/velin-release-changelog-sync/SKILL.md +57 -0
  194. package/packages/velinstyle-skills/skills/velin-release-meta-rebuild/SKILL.md +57 -0
  195. package/packages/velinstyle-skills/skills/velin-review-conversion-hero/SKILL.md +57 -0
  196. package/packages/velinstyle-skills/skills/velin-review-page-gate/SKILL.md +57 -0
  197. package/packages/velinstyle-skills/skills/velin-review-seo-meta/SKILL.md +57 -0
  198. package/packages/velinstyle-skills/skills/velin-security-sanitize-html/SKILL.md +57 -0
  199. package/packages/velinstyle-skills/skills/velin-security-scan-pii/SKILL.md +57 -0
  200. package/packages/velinstyle-skills/skills/velin-testing-a11y-suite/SKILL.md +57 -0
  201. package/packages/velinstyle-skills/skills/velin-testing-visual-smoke/SKILL.md +57 -0
  202. package/packages/velinstyle-skills/skills/velin-themes-apply-token/SKILL.md +57 -0
  203. package/packages/velinstyle-skills/skills/velin-themes-contrast-check/SKILL.md +57 -0
  204. package/packages/velinstyle-skills/skills/velin-utilities-layout-apply/SKILL.md +57 -0
  205. package/packages/velinstyle-skills/skills/velin-utilities-prefix-fix/SKILL.md +57 -0
  206. package/packages/velinstyle-skills/skills/velin-utilities-token-map/SKILL.md +57 -0
  207. package/packages/velinstyle-skills/templates/admin-panel.template.yaml +12 -0
  208. package/packages/velinstyle-skills/templates/blog.template.yaml +12 -0
  209. package/packages/velinstyle-skills/templates/documentation-portal.template.yaml +12 -0
  210. package/packages/velinstyle-skills/templates/ecommerce-shop.template.yaml +13 -0
  211. package/packages/velinstyle-skills/templates/landing-page.template.yaml +12 -0
  212. package/packages/velinstyle-skills/templates/laravel-dashboard.template.yaml +11 -0
  213. package/packages/velinstyle-skills/templates/marketing-website.template.yaml +13 -0
  214. package/packages/velinstyle-skills/templates/portfolio.template.yaml +12 -0
  215. package/schemas/component-knowledge.schema.json +33 -0
  216. package/schemas/design-constraint.schema.json +15 -0
  217. package/schemas/design-intelligence.schema.json +19 -0
  218. package/schemas/design-rule.schema.json +19 -0
  219. package/schemas/page-template.schema.json +24 -0
  220. package/schemas/review-report.schema.json +36 -0
  221. package/schemas/section.schema.json +22 -0
  222. package/schemas/skill-bundle.schema.json +15 -0
  223. package/schemas/skill-graph.schema.json +25 -0
  224. package/schemas/skill-pack.schema.json +14 -0
  225. package/schemas/skill-project.schema.json +16 -0
  226. package/schemas/skill-record.schema.json +27 -0
  227. package/schemas/skill-registry.schema.json +17 -0
  228. package/schemas/skill-template.schema.json +17 -0
  229. package/schemas/token-graph.schema.json +27 -0
  230. package/schemas/utility.schema.json +166 -0
  231. package/src/components/alert.css +22 -1
  232. package/src/components/calendar-dropzone.css +5 -0
  233. package/src/layout/app-shell.css +33 -0
  234. package/src/tokens/shadow.css +13 -0
  235. package/src/utilities/border.css +2 -0
  236. package/src/utilities/display.css +1 -24
  237. package/src/utilities/responsive.css +16 -1
  238. package/src/utilities/spacing.css +32 -0
  239. package/src/velinstyle.css +2 -0
  240. package/dist/chunks/attributes-3BZLI7XF.js +0 -364
  241. package/dist/chunks/attributes-4N5JP4CG.js +0 -364
  242. package/dist/chunks/attributes-5Q2WXGRC.js +0 -374
  243. package/dist/chunks/attributes-AIR7SVLK.js +0 -364
  244. package/dist/chunks/attributes-BGRN5XZO.js +0 -364
  245. package/dist/chunks/attributes-BVSQAYLR.js +0 -364
  246. package/dist/chunks/attributes-CDYFUY7Y.js +0 -364
  247. package/dist/chunks/attributes-JMYJZBPE.js +0 -364
  248. package/dist/chunks/attributes-R5JY3X4O.js +0 -374
  249. package/dist/chunks/attributes-TNSPQTHX.js +0 -374
  250. package/dist/chunks/chunk-2354NEBP.js +0 -109
  251. package/dist/chunks/chunk-2VNA7G7S.js +0 -109
  252. package/dist/chunks/chunk-AQLRJSGG.js +0 -109
  253. package/dist/chunks/chunk-EWPSDMQT.js +0 -109
  254. package/dist/chunks/chunk-LA7264K4.js +0 -85
  255. package/dist/chunks/chunk-QTJJ3DPO.js +0 -109
  256. package/dist/chunks/chunk-RZQVWFHW.js +0 -109
  257. package/dist/chunks/chunk-U4XHMZ7D.js +0 -109
  258. package/dist/chunks/chunk-V5YIUA6G.js +0 -109
  259. package/dist/chunks/chunk-XIET2VSZ.js +0 -109
  260. package/dist/chunks/chunk-XYLJ2GCB.js +0 -205
  261. package/dist/chunks/chunk-ZPSPKUYD.js +0 -109
  262. package/dist/chunks/highlight-XTHRKBA3.js +0 -37
  263. package/dist/chunks/velin-bottom-nav-2N2TYWOF.js +0 -86
  264. package/dist/chunks/velin-carousel-Y5VCOABZ.js +0 -213
  265. package/dist/chunks/velin-code-block-ASUBTAQV.js +0 -119
  266. package/dist/chunks/velin-code-block-TSUKPY4C.js +0 -123
  267. package/dist/chunks/velin-code-block-Y6CM726Q.js +0 -119
  268. package/dist/chunks/velin-combobox-2KDTCQ7N.js +0 -155
  269. package/dist/chunks/velin-command-M7RNHUPR.js +0 -136
  270. package/dist/chunks/velin-copy-T5KDTDXP.js +0 -81
  271. package/dist/chunks/velin-countdown-5XSTN3BH.js +0 -101
  272. package/dist/chunks/velin-counter-ISCTEAHI.js +0 -118
  273. package/dist/chunks/velin-dialog-D2GUHSCD.js +0 -144
  274. package/dist/chunks/velin-dialog-IJLFDXAJ.js +0 -144
  275. package/dist/chunks/velin-dialog-TNS3WXMB.js +0 -144
  276. package/dist/chunks/velin-drawer-MJS6WCF7.js +0 -130
  277. package/dist/chunks/velin-email-N5B5ZYTE.js +0 -90
  278. package/dist/chunks/velin-icon-KZO3IEHG.js +0 -164
  279. package/dist/chunks/velin-lightbox-I75U6JF4.js +0 -140
  280. package/dist/chunks/velin-lightbox-QOTB4PRL.js +0 -140
  281. package/dist/chunks/velin-lightbox-UCD6N7HF.js +0 -140
  282. package/dist/chunks/velin-live-dot-XHUZCIDZ.js +0 -67
  283. package/dist/chunks/velin-menubar-SFEXJE56.js +0 -86
  284. package/dist/chunks/velin-modal-2HOBXE6F.js +0 -176
  285. package/dist/chunks/velin-modal-GLI2XZZB.js +0 -176
  286. package/dist/chunks/velin-popover-EXINRIGJ.js +0 -145
  287. package/dist/chunks/velin-popover-OXX7MRZ6.js +0 -145
  288. package/dist/chunks/velin-popover-YKCCROJG.js +0 -145
  289. package/dist/chunks/velin-rating-XRQJV4LO.js +0 -91
  290. package/dist/chunks/velin-scroll-top-F2FCZNYD.js +0 -58
  291. package/dist/chunks/velin-search-4YHJWYSS.js +0 -556
  292. package/dist/chunks/velin-search-LWHY23Q5.js +0 -474
  293. package/dist/chunks/velin-secure-field-H7FSBUJW.js +0 -95
  294. package/dist/chunks/velin-segmented-control-PQX6LKOJ.js +0 -109
  295. package/dist/chunks/velin-sheet-3OGI4HD7.js +0 -119
  296. package/dist/chunks/velin-sparkline-GVEANJVW.js +0 -184
  297. package/dist/chunks/velin-sparkline-KDA3GQAN.js +0 -162
  298. package/dist/chunks/velin-stepper-2ZIHLKGM.js +0 -141
  299. package/dist/chunks/velin-stepper-FYEUEWE6.js +0 -141
  300. package/dist/chunks/velin-stepper-wc-QU3KRVQR.js +0 -133
  301. package/dist/chunks/velin-theme-toggle-BNNS7WLV.js +0 -285
  302. package/dist/chunks/velin-theme-toggle-NO7V4TWI.js +0 -285
  303. package/dist/chunks/velin-theme-toggle-QELCJM2Q.js +0 -291
  304. package/dist/chunks/velin-toast-RCZ4CSUC.js +0 -109
  305. package/dist/chunks/velin-toast-WEUBTJG6.js +0 -109
  306. package/dist/chunks/velin-tooltip-664IOHZA.js +0 -112
  307. package/dist/chunks/velin-tooltip-wc-LXDVT6DE.js +0 -103
  308. package/dist/chunks/worker-client-R6DBYPFT.js +0 -46
@@ -0,0 +1,154 @@
1
+ import {
2
+ escapeHTML
3
+ } from "./chunk-RDE3QE7Z.js";
4
+
5
+ // components/velin-file-dropzone.js
6
+ var styles = `
7
+ :host { display: block; }
8
+ .zone {
9
+ border: 2px dashed var(--velin-color-border, #cbd5e1);
10
+ border-radius: var(--velin-radius-md, 0.5rem);
11
+ padding: var(--velin-space-6, 1.5rem);
12
+ background: var(--velin-color-surface-dim, var(--velin-color-bg-subtle, #f8fafc));
13
+ color: var(--velin-color-text, #111);
14
+ text-align: center;
15
+ transition: border-color 150ms ease, background 150ms ease;
16
+ }
17
+ :host([dragging]) .zone {
18
+ border-color: var(--velin-color-primary, #2563eb);
19
+ background: var(--velin-color-primary-subtle, #eff6ff);
20
+ }
21
+ .hint { margin: 0 0 var(--velin-space-3, 0.75rem); color: var(--velin-color-text-muted, #64748b); }
22
+ .browse {
23
+ display: inline-flex; align-items: center; justify-content: center;
24
+ min-block-size: 2.75rem; padding-inline: var(--velin-space-4, 1rem);
25
+ border-radius: var(--velin-radius-md, 0.5rem);
26
+ border: none; cursor: pointer;
27
+ background: var(--velin-color-primary, #2563eb);
28
+ color: var(--velin-color-on-primary, #fff);
29
+ font: inherit;
30
+ }
31
+ .browse:focus-visible { outline: 2px solid var(--velin-color-focus, #2563eb); outline-offset: 2px; }
32
+ input[type="file"] {
33
+ position: absolute; inline-size: 1px; block-size: 1px; padding: 0; margin: -1px;
34
+ overflow: hidden; clip: rect(0,0,0,0); border: 0;
35
+ }
36
+ .list { list-style: none; padding: 0; margin: var(--velin-space-4, 1rem) 0 0; text-align: start; }
37
+ .list li {
38
+ display: flex; justify-content: space-between; gap: var(--velin-space-3, 0.75rem);
39
+ padding: var(--velin-space-2, 0.5rem) 0;
40
+ border-block-end: 1px solid var(--velin-color-border, #e2e8f0);
41
+ font-size: var(--velin-text-sm, 0.875rem);
42
+ }
43
+ .progress {
44
+ margin-block-start: var(--velin-space-3, 0.75rem);
45
+ block-size: 0.5rem; border-radius: 999px;
46
+ background: var(--velin-color-border, #e2e8f0); overflow: hidden;
47
+ }
48
+ .bar {
49
+ block-size: 100%; inline-size: 0%;
50
+ background: var(--velin-color-primary, #2563eb);
51
+ transition: inline-size 150ms ease;
52
+ }
53
+ .status { margin: var(--velin-space-2, 0.5rem) 0 0; font-size: var(--velin-text-sm, 0.875rem); }
54
+ .status[data-tone="error"] { color: var(--velin-color-danger, #b91c1c); }
55
+ `;
56
+ var VelinFileDropzone = class extends HTMLElement {
57
+ static get observedAttributes() {
58
+ return ["accept", "multiple", "label", "progress"];
59
+ }
60
+ constructor() {
61
+ super();
62
+ this.attachShadow({ mode: "open" });
63
+ this._files = [];
64
+ }
65
+ connectedCallback() {
66
+ this._render();
67
+ }
68
+ attributeChangedCallback() {
69
+ if (this.shadowRoot?.querySelector(".zone")) this._render();
70
+ }
71
+ get files() {
72
+ return this._files.slice();
73
+ }
74
+ _emitFiles(fileList) {
75
+ const accept = this.getAttribute("accept");
76
+ const files = [...fileList];
77
+ if (accept) {
78
+ const parts = accept.split(",").map((s) => s.trim().toLowerCase());
79
+ const bad = files.find((f) => {
80
+ const name = f.name.toLowerCase();
81
+ const type = (f.type || "").toLowerCase();
82
+ return !parts.some((p) => p.startsWith(".") ? name.endsWith(p) : type === p || type.startsWith(p.replace("/*", "/")));
83
+ });
84
+ if (bad) {
85
+ this._setStatus(`File type not allowed: ${bad.name}`, "error");
86
+ this.dispatchEvent(new CustomEvent("velin-error", { bubbles: true, detail: { message: "accept", file: bad } }));
87
+ return;
88
+ }
89
+ }
90
+ this._files = files;
91
+ this._setStatus(files.length ? `${files.length} file(s) ready` : "", "ok");
92
+ this.dispatchEvent(new CustomEvent("velin-files", { bubbles: true, detail: { files } }));
93
+ this._renderList();
94
+ }
95
+ _setStatus(text, tone = "ok") {
96
+ const el = this.shadowRoot?.querySelector(".status");
97
+ if (!el) return;
98
+ el.textContent = text;
99
+ el.dataset.tone = tone;
100
+ }
101
+ _renderList() {
102
+ const ul = this.shadowRoot?.querySelector(".list");
103
+ if (!ul) return;
104
+ ul.innerHTML = this._files.map((f) => `<li><span>${escapeHTML(f.name)}</span><span>${Math.round(f.size / 1024)} KB</span></li>`).join("");
105
+ }
106
+ _render() {
107
+ const label = escapeHTML(this.getAttribute("label") || "Upload files");
108
+ const accept = this.getAttribute("accept") || "";
109
+ const multiple = this.hasAttribute("multiple");
110
+ const progress = Math.max(0, Math.min(100, Number(this.getAttribute("progress") || 0)));
111
+ this.shadowRoot.innerHTML = `
112
+ <style>${styles}</style>
113
+ <div class="zone" role="group" aria-label="${label}">
114
+ <p class="hint">Drag and drop files here, or browse. Client-side only \u2014 wire <code>velin-files</code> to your upload API.</p>
115
+ <button type="button" class="browse">Browse files</button>
116
+ <input type="file" ${accept ? `accept="${escapeHTML(accept)}"` : ""} ${multiple ? "multiple" : ""} />
117
+ <div class="progress" hidden="${progress <= 0 ? "true" : "false"}" aria-hidden="${progress <= 0 ? "true" : "false"}">
118
+ <div class="bar" style="inline-size:${progress}%"></div>
119
+ </div>
120
+ <p class="status" role="status" aria-live="polite"></p>
121
+ <ul class="list"></ul>
122
+ </div>
123
+ `;
124
+ const input = this.shadowRoot.querySelector("input");
125
+ const browse = this.shadowRoot.querySelector(".browse");
126
+ const zone = this.shadowRoot.querySelector(".zone");
127
+ browse.addEventListener("click", () => input.click());
128
+ input.addEventListener("change", () => {
129
+ if (input.files?.length) this._emitFiles(input.files);
130
+ });
131
+ ["dragenter", "dragover"].forEach((ev) => {
132
+ zone.addEventListener(ev, (e) => {
133
+ e.preventDefault();
134
+ this.setAttribute("dragging", "");
135
+ });
136
+ });
137
+ ["dragleave", "drop"].forEach((ev) => {
138
+ zone.addEventListener(ev, (e) => {
139
+ e.preventDefault();
140
+ this.removeAttribute("dragging");
141
+ });
142
+ });
143
+ zone.addEventListener("drop", (e) => {
144
+ const list = e.dataTransfer?.files;
145
+ if (list?.length) this._emitFiles(list);
146
+ });
147
+ this._renderList();
148
+ }
149
+ };
150
+ customElements.define("velin-file-dropzone", VelinFileDropzone);
151
+ var velin_file_dropzone_default = VelinFileDropzone;
152
+ export {
153
+ velin_file_dropzone_default as default
154
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  sanitizeSVG,
3
3
  sanitizeURL
4
- } from "./chunk-MKZP2TBH.js";
4
+ } from "./chunk-L7ZGUU4D.js";
5
5
 
6
6
  // components/velin-icon.js
7
7
  var PROVIDER_CDNS = {
@@ -29,7 +29,21 @@ function resolveProviderUrl(provider, variant) {
29
29
  return PROVIDER_CDNS[provider];
30
30
  }
31
31
  var _svgCache = /* @__PURE__ */ new Map();
32
+ var DEFAULT_SPRITE = "velin-icons.svg";
33
+ function resolveDefaultSpriteUrl() {
34
+ if (typeof document !== "undefined") {
35
+ const meta = document.querySelector('meta[name="velin-icon-sprite"]');
36
+ const fromMeta = meta?.getAttribute("content")?.trim();
37
+ if (fromMeta) return fromMeta;
38
+ const fromHtml = document.documentElement?.getAttribute("data-velin-icon-sprite")?.trim();
39
+ if (fromHtml) return fromHtml;
40
+ }
41
+ const configured = typeof VelinIcon.defaultSprite === "string" ? VelinIcon.defaultSprite.trim() : "";
42
+ return configured || DEFAULT_SPRITE;
43
+ }
32
44
  var VelinIcon = class extends HTMLElement {
45
+ /** @type {string} Relative or absolute sprite URL used when `sprite` attribute is omitted. */
46
+ static defaultSprite = DEFAULT_SPRITE;
33
47
  static get observedAttributes() {
34
48
  return ["name", "size", "label", "provider", "variant", "sprite"];
35
49
  }
@@ -46,7 +60,7 @@ var VelinIcon = class extends HTMLElement {
46
60
  _render() {
47
61
  const name = this.getAttribute("name");
48
62
  const size = this.getAttribute("size") || "24";
49
- const label = this.getAttribute("label");
63
+ const a11y = this._resolveA11y();
50
64
  const provider = this.getAttribute("provider");
51
65
  const variant = this.getAttribute("variant");
52
66
  if (!name) {
@@ -54,12 +68,18 @@ var VelinIcon = class extends HTMLElement {
54
68
  return;
55
69
  }
56
70
  if (provider && (PROVIDER_CDNS[provider] || PROVIDER_VARIANTS[provider])) {
57
- this._renderFromCDN(name, size, label, provider, variant);
71
+ this._renderFromCDN(name, size, a11y, provider, variant);
58
72
  return;
59
73
  }
60
- this._renderFromSprite(name, size, label);
74
+ this._renderFromSprite(name, size, a11y);
75
+ }
76
+ _resolveA11y() {
77
+ const label = (this.getAttribute("label") || this.getAttribute("aria-label") || "").trim();
78
+ if (label) return { label, hidden: false };
79
+ const hidden = this.getAttribute("aria-hidden") !== "false";
80
+ return { label: "", hidden };
61
81
  }
62
- _renderFromSprite(name, size, label) {
82
+ _renderFromSprite(name, size, a11y) {
63
83
  const svgNS = "http://www.w3.org/2000/svg";
64
84
  const svg = document.createElementNS(svgNS, "svg");
65
85
  svg.setAttribute("width", size);
@@ -71,7 +91,6 @@ var VelinIcon = class extends HTMLElement {
71
91
  svg.setAttribute("stroke-linecap", "round");
72
92
  svg.setAttribute("stroke-linejoin", "round");
73
93
  this._applyStyle(svg);
74
- this._applyA11y(svg, label);
75
94
  const use = document.createElementNS(svgNS, "use");
76
95
  const spriteAttr = this.getAttribute("sprite");
77
96
  const localSymbol = document.getElementById(name);
@@ -80,29 +99,31 @@ var VelinIcon = class extends HTMLElement {
80
99
  if (spriteAttr === "" || spriteAttr == null && isLocalSymbol) {
81
100
  href = `#${name}`;
82
101
  } else {
83
- const spriteUrl = sanitizeURL(spriteAttr || "/dist/velin-icons.svg") || "/dist/velin-icons.svg";
102
+ const fallback = resolveDefaultSpriteUrl();
103
+ const spriteUrl = sanitizeURL(spriteAttr || fallback) || fallback || DEFAULT_SPRITE;
84
104
  href = `${spriteUrl}#${name}`;
85
105
  }
86
106
  use.setAttribute("href", href);
87
107
  svg.appendChild(use);
108
+ this._applyA11y(svg, a11y);
88
109
  this.innerHTML = "";
89
110
  this.appendChild(svg);
90
111
  this._rendered = true;
91
112
  }
92
- async _renderFromCDN(name, size, label, provider, variant) {
113
+ async _renderFromCDN(name, size, a11y, provider, variant) {
93
114
  const cacheKey = `${provider}:${variant || "default"}:${name}`;
94
115
  if (_svgCache.has(cacheKey)) {
95
- this._injectSVG(_svgCache.get(cacheKey), size, label);
116
+ this._injectSVG(_svgCache.get(cacheKey), size, a11y);
96
117
  return;
97
118
  }
98
119
  const template = resolveProviderUrl(provider, variant);
99
120
  if (!template) {
100
- this._renderFromSprite(name, size, label);
121
+ this._renderFromSprite(name, size, a11y);
101
122
  return;
102
123
  }
103
124
  const url = sanitizeURL(template.replace("{name}", name));
104
125
  if (!url) {
105
- this._renderFromSprite(name, size, label);
126
+ this._renderFromSprite(name, size, a11y);
106
127
  return;
107
128
  }
108
129
  try {
@@ -112,12 +133,20 @@ var VelinIcon = class extends HTMLElement {
112
133
  if (!text.includes("<svg")) throw new Error("Not SVG");
113
134
  const clean = await sanitizeSVG(text);
114
135
  _svgCache.set(cacheKey, clean);
115
- this._injectSVG(clean, size, label);
136
+ this._injectSVG(clean, size, a11y);
116
137
  } catch {
117
- this._renderFromSprite(name, size, label);
138
+ this._renderFromSprite(name, size, a11y);
118
139
  }
119
140
  }
120
- _injectSVG(svgText, size, label) {
141
+ _stripForeignA11y(svg) {
142
+ svg.removeAttribute("role");
143
+ svg.removeAttribute("aria-label");
144
+ svg.removeAttribute("aria-labelledby");
145
+ svg.removeAttribute("aria-hidden");
146
+ svg.querySelector("title")?.remove();
147
+ svg.querySelector("desc")?.remove();
148
+ }
149
+ _injectSVG(svgText, size, a11y) {
121
150
  const parser = new DOMParser();
122
151
  const doc = parser.parseFromString(svgText, "image/svg+xml");
123
152
  const svg = doc.querySelector("svg");
@@ -125,11 +154,12 @@ var VelinIcon = class extends HTMLElement {
125
154
  this.innerHTML = "";
126
155
  return;
127
156
  }
157
+ this._stripForeignA11y(svg);
128
158
  svg.setAttribute("width", size);
129
159
  svg.setAttribute("height", size);
130
160
  if (!svg.getAttribute("viewBox")) svg.setAttribute("viewBox", "0 0 24 24");
131
161
  this._applyStyle(svg);
132
- this._applyA11y(svg, label);
162
+ this._applyA11y(svg, a11y);
133
163
  this.innerHTML = "";
134
164
  this.appendChild(document.importNode(svg, true));
135
165
  this._rendered = true;
@@ -139,12 +169,24 @@ var VelinIcon = class extends HTMLElement {
139
169
  svg.style.verticalAlign = "middle";
140
170
  svg.style.flexShrink = "0";
141
171
  }
142
- _applyA11y(svg, label) {
172
+ _applyA11y(svg, a11y) {
173
+ const { label, hidden } = a11y;
174
+ const use = svg.querySelector("use");
143
175
  if (label) {
144
176
  svg.setAttribute("role", "img");
145
177
  svg.setAttribute("aria-label", label);
146
- } else {
178
+ svg.removeAttribute("aria-hidden");
179
+ svg.removeAttribute("focusable");
180
+ if (use) use.removeAttribute("aria-hidden");
181
+ } else if (hidden) {
182
+ svg.setAttribute("role", "presentation");
147
183
  svg.setAttribute("aria-hidden", "true");
184
+ svg.setAttribute("focusable", "false");
185
+ svg.removeAttribute("aria-label");
186
+ if (use) {
187
+ use.setAttribute("aria-hidden", "true");
188
+ use.setAttribute("focusable", "false");
189
+ }
148
190
  }
149
191
  }
150
192
  static get providers() {
@@ -29,9 +29,23 @@ function resolveProviderUrl(provider, variant) {
29
29
  return PROVIDER_CDNS[provider];
30
30
  }
31
31
  var _svgCache = /* @__PURE__ */ new Map();
32
+ var DEFAULT_SPRITE = "velin-icons.svg";
33
+ function resolveDefaultSpriteUrl() {
34
+ if (typeof document !== "undefined") {
35
+ const meta = document.querySelector('meta[name="velin-icon-sprite"]');
36
+ const fromMeta = meta?.getAttribute("content")?.trim();
37
+ if (fromMeta) return fromMeta;
38
+ const fromHtml = document.documentElement?.getAttribute("data-velin-icon-sprite")?.trim();
39
+ if (fromHtml) return fromHtml;
40
+ }
41
+ const configured = typeof VelinIcon.defaultSprite === "string" ? VelinIcon.defaultSprite.trim() : "";
42
+ return configured || DEFAULT_SPRITE;
43
+ }
32
44
  var VelinIcon = class extends HTMLElement {
45
+ /** @type {string} Relative or absolute sprite URL used when `sprite` attribute is omitted. */
46
+ static defaultSprite = DEFAULT_SPRITE;
33
47
  static get observedAttributes() {
34
- return ["name", "size", "label", "provider", "variant", "sprite", "aria-hidden", "aria-label"];
48
+ return ["name", "size", "label", "provider", "variant", "sprite"];
35
49
  }
36
50
  constructor() {
37
51
  super();
@@ -77,7 +91,6 @@ var VelinIcon = class extends HTMLElement {
77
91
  svg.setAttribute("stroke-linecap", "round");
78
92
  svg.setAttribute("stroke-linejoin", "round");
79
93
  this._applyStyle(svg);
80
- this._applyA11y(svg, a11y);
81
94
  const use = document.createElementNS(svgNS, "use");
82
95
  const spriteAttr = this.getAttribute("sprite");
83
96
  const localSymbol = document.getElementById(name);
@@ -86,11 +99,13 @@ var VelinIcon = class extends HTMLElement {
86
99
  if (spriteAttr === "" || spriteAttr == null && isLocalSymbol) {
87
100
  href = `#${name}`;
88
101
  } else {
89
- const spriteUrl = sanitizeURL(spriteAttr || "/dist/velin-icons.svg") || "/dist/velin-icons.svg";
102
+ const fallback = resolveDefaultSpriteUrl();
103
+ const spriteUrl = sanitizeURL(spriteAttr || fallback) || fallback || DEFAULT_SPRITE;
90
104
  href = `${spriteUrl}#${name}`;
91
105
  }
92
106
  use.setAttribute("href", href);
93
107
  svg.appendChild(use);
108
+ this._applyA11y(svg, a11y);
94
109
  this.innerHTML = "";
95
110
  this.appendChild(svg);
96
111
  this._rendered = true;
@@ -162,14 +177,12 @@ var VelinIcon = class extends HTMLElement {
162
177
  svg.setAttribute("aria-label", label);
163
178
  svg.removeAttribute("aria-hidden");
164
179
  svg.removeAttribute("focusable");
165
- this.removeAttribute("aria-hidden");
166
180
  if (use) use.removeAttribute("aria-hidden");
167
181
  } else if (hidden) {
168
182
  svg.setAttribute("role", "presentation");
169
183
  svg.setAttribute("aria-hidden", "true");
170
184
  svg.setAttribute("focusable", "false");
171
185
  svg.removeAttribute("aria-label");
172
- this.setAttribute("aria-hidden", "true");
173
186
  if (use) {
174
187
  use.setAttribute("aria-hidden", "true");
175
188
  use.setAttribute("focusable", "false");
@@ -1,11 +1,11 @@
1
- import {
2
- announce
3
- } from "./chunk-Z4JYQ2XX.js";
4
1
  import {
5
2
  clearBackgroundInert,
6
3
  setBackgroundInert,
7
4
  trapFocus
8
5
  } from "./chunk-42VVPW6N.js";
6
+ import {
7
+ announce
8
+ } from "./chunk-Z4JYQ2XX.js";
9
9
  import {
10
10
  escapeHTML,
11
11
  sanitizeURL
@@ -101,7 +101,6 @@ var VelinLightbox = class extends HTMLElement {
101
101
  this.setAttribute("open", "");
102
102
  setBackgroundInert(this);
103
103
  this._render();
104
- document.body.style.overflow = "hidden";
105
104
  const overlay = this.shadowRoot.querySelector(".overlay");
106
105
  overlay.removeEventListener("keydown", this._onTrapKey);
107
106
  overlay.addEventListener("keydown", this._onTrapKey);
@@ -109,14 +108,16 @@ var VelinLightbox = class extends HTMLElement {
109
108
  }
110
109
  close() {
111
110
  this.removeAttribute("open");
112
- clearBackgroundInert();
113
- document.body.style.overflow = "";
111
+ clearBackgroundInert(this);
114
112
  if (this._previousFocus) {
115
113
  this._previousFocus.focus();
116
114
  this._previousFocus = null;
117
115
  }
118
116
  this.dispatchEvent(new CustomEvent("velin-close", { bubbles: true }));
119
117
  }
118
+ disconnectedCallback() {
119
+ clearBackgroundInert(this);
120
+ }
120
121
  _prev() {
121
122
  this._index = (this._index - 1 + this._items.length) % this._items.length;
122
123
  this._render();
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  escapeHTML,
11
11
  sanitizeURL
12
- } from "./chunk-RDE3QE7Z.js";
12
+ } from "./chunk-L7ZGUU4D.js";
13
13
 
14
14
  // components/velin-lightbox.js
15
15
  var styles = `
@@ -101,7 +101,6 @@ var VelinLightbox = class extends HTMLElement {
101
101
  this.setAttribute("open", "");
102
102
  setBackgroundInert(this);
103
103
  this._render();
104
- document.body.style.overflow = "hidden";
105
104
  const overlay = this.shadowRoot.querySelector(".overlay");
106
105
  overlay.removeEventListener("keydown", this._onTrapKey);
107
106
  overlay.addEventListener("keydown", this._onTrapKey);
@@ -109,14 +108,16 @@ var VelinLightbox = class extends HTMLElement {
109
108
  }
110
109
  close() {
111
110
  this.removeAttribute("open");
112
- clearBackgroundInert();
113
- document.body.style.overflow = "";
111
+ clearBackgroundInert(this);
114
112
  if (this._previousFocus) {
115
113
  this._previousFocus.focus();
116
114
  this._previousFocus = null;
117
115
  }
118
116
  this.dispatchEvent(new CustomEvent("velin-close", { bubbles: true }));
119
117
  }
118
+ disconnectedCallback() {
119
+ clearBackgroundInert(this);
120
+ }
120
121
  _prev() {
121
122
  this._index = (this._index - 1 + this._items.length) % this._items.length;
122
123
  this._render();
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-42VVPW6N.js";
7
7
  import {
8
8
  escapeHTML
9
- } from "./chunk-LA7264K4.js";
9
+ } from "./chunk-L7ZGUU4D.js";
10
10
 
11
11
  // components/velin-menubar.js
12
12
  var styles = `
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-42VVPW6N.js";
9
9
  import {
10
10
  escapeHTML
11
- } from "./chunk-MKZP2TBH.js";
11
+ } from "./chunk-L7ZGUU4D.js";
12
12
 
13
13
  // components/velin-modal.js
14
14
  var styles = `
@@ -105,14 +105,15 @@ var VelinModal = class extends HTMLElement {
105
105
  this._onKeydown = this._onKeydown.bind(this);
106
106
  }
107
107
  connectedCallback() {
108
- const title = this.getAttribute("title") || "";
108
+ const title = (this.getAttribute("title") || "").trim();
109
109
  const safeTitle = escapeHTML(title);
110
+ const dialogLabel = title ? 'aria-labelledby="velin-modal-title"' : `aria-label="${escapeHTML(this.getAttribute("aria-label") || "Dialog")}"`;
110
111
  this.shadowRoot.innerHTML = `
111
112
  <style>${styles}</style>
112
113
  <div class="overlay" part="overlay">
113
- <div class="dialog" role="dialog" aria-modal="true" aria-labelledby="velin-modal-title" part="dialog">
114
+ <div class="dialog" role="dialog" aria-modal="true" ${dialogLabel} part="dialog">
114
115
  <div class="header" part="header">
115
- <h2 class="title" id="velin-modal-title">${safeTitle}</h2>
116
+ <h2 class="title" id="velin-modal-title"${title ? "" : ' class="velin-sr-only"'}>${safeTitle || "Dialog"}</h2>
116
117
  <button class="close-btn" aria-label="Close" part="close">&#215;</button>
117
118
  </div>
118
119
  <div class="body" part="body"><slot></slot></div>
@@ -145,7 +146,6 @@ var VelinModal = class extends HTMLElement {
145
146
  this._previouslyFocused = saveFocus();
146
147
  setBackgroundInert(this);
147
148
  document.addEventListener("keydown", this._onKeydown);
148
- document.body.style.overflow = "hidden";
149
149
  requestAnimationFrame(() => {
150
150
  const focusable = getFocusableElements(this.shadowRoot);
151
151
  if (focusable.length > 0) focusable[0].focus();
@@ -153,8 +153,7 @@ var VelinModal = class extends HTMLElement {
153
153
  }
154
154
  _close() {
155
155
  document.removeEventListener("keydown", this._onKeydown);
156
- document.body.style.overflow = "";
157
- clearBackgroundInert();
156
+ clearBackgroundInert(this);
158
157
  restoreFocus(this._previouslyFocused);
159
158
  }
160
159
  _onKeydown(event) {
@@ -166,7 +165,7 @@ var VelinModal = class extends HTMLElement {
166
165
  }
167
166
  disconnectedCallback() {
168
167
  document.removeEventListener("keydown", this._onKeydown);
169
- document.body.style.overflow = "";
168
+ clearBackgroundInert(this);
170
169
  }
171
170
  };
172
171
  customElements.define("velin-modal", VelinModal);
@@ -146,7 +146,6 @@ var VelinModal = class extends HTMLElement {
146
146
  this._previouslyFocused = saveFocus();
147
147
  setBackgroundInert(this);
148
148
  document.addEventListener("keydown", this._onKeydown);
149
- document.body.style.overflow = "hidden";
150
149
  requestAnimationFrame(() => {
151
150
  const focusable = getFocusableElements(this.shadowRoot);
152
151
  if (focusable.length > 0) focusable[0].focus();
@@ -154,8 +153,7 @@ var VelinModal = class extends HTMLElement {
154
153
  }
155
154
  _close() {
156
155
  document.removeEventListener("keydown", this._onKeydown);
157
- document.body.style.overflow = "";
158
- clearBackgroundInert();
156
+ clearBackgroundInert(this);
159
157
  restoreFocus(this._previouslyFocused);
160
158
  }
161
159
  _onKeydown(event) {
@@ -167,7 +165,7 @@ var VelinModal = class extends HTMLElement {
167
165
  }
168
166
  disconnectedCallback() {
169
167
  document.removeEventListener("keydown", this._onKeydown);
170
- document.body.style.overflow = "";
168
+ clearBackgroundInert(this);
171
169
  }
172
170
  };
173
171
  customElements.define("velin-modal", VelinModal);
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-42VVPW6N.js";
7
7
  import {
8
8
  escapeHTML
9
- } from "./chunk-RDE3QE7Z.js";
9
+ } from "./chunk-L7ZGUU4D.js";
10
10
 
11
11
  // components/velin-popover.js
12
12
  var styles = `
@@ -65,23 +65,44 @@ var VelinPopover = class extends HTMLElement {
65
65
  </div>
66
66
  `;
67
67
  const popoverEl = this.shadowRoot.querySelector(".popover");
68
- if (!title) {
69
- const ariaLabel = this.getAttribute("aria-label");
70
- if (ariaLabel && popoverEl) popoverEl.setAttribute("aria-label", ariaLabel);
68
+ if (!title && popoverEl) {
69
+ const fallback = this.getAttribute("aria-label") || (role === "tooltip" ? "Tooltip" : "Popover");
70
+ popoverEl.setAttribute("aria-label", fallback);
71
71
  }
72
72
  const triggerSlot = this.shadowRoot.querySelector('slot[name="trigger"]');
73
73
  triggerSlot.addEventListener("slotchange", () => this._wireTrigger(triggerType));
74
74
  this._wireTrigger(triggerType);
75
75
  }
76
+ _ensureTriggerInteractive(trigger) {
77
+ const tag = trigger.tagName;
78
+ if (tag !== "BUTTON" && tag !== "A" && trigger.getAttribute("role") !== "button") {
79
+ trigger.setAttribute("role", "button");
80
+ if (!trigger.hasAttribute("tabindex")) trigger.setAttribute("tabindex", "0");
81
+ }
82
+ }
83
+ _onTriggerKey(e) {
84
+ if (e.key === "Escape") {
85
+ this.close();
86
+ return;
87
+ }
88
+ if (e.key === "Enter" || e.key === " ") {
89
+ e.preventDefault();
90
+ this.toggle();
91
+ }
92
+ }
76
93
  _wireTrigger(triggerType) {
77
94
  const trigger = this.shadowRoot.querySelector('slot[name="trigger"]')?.assignedElements()[0];
78
95
  if (!trigger) return;
96
+ this._ensureTriggerInteractive(trigger);
79
97
  const isHover = triggerType === "hover";
80
98
  trigger.setAttribute("aria-haspopup", isHover ? "true" : "dialog");
81
99
  trigger.setAttribute("aria-expanded", this.hasAttribute("open") ? "true" : "false");
82
100
  if (this._isDialog) {
83
101
  trigger.setAttribute("aria-controls", this._popoverId);
84
102
  }
103
+ trigger.removeEventListener("keydown", this._onTriggerKeyBound);
104
+ this._onTriggerKeyBound = this._onTriggerKeyBound || this._onTriggerKey.bind(this);
105
+ trigger.addEventListener("keydown", this._onTriggerKeyBound);
85
106
  if (triggerType === "click") {
86
107
  trigger.onclick = () => this.toggle();
87
108
  } else if (triggerType === "hover") {
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-42VVPW6N.js";
7
7
  import {
8
8
  escapeHTML
9
- } from "./chunk-MKZP2TBH.js";
9
+ } from "./chunk-L7ZGUU4D.js";
10
10
 
11
11
  // components/velin-rating.js
12
12
  var styles = `
@@ -284,7 +284,7 @@ function createSearch(config = {}) {
284
284
  async function getWorker() {
285
285
  if (!wantWorker || workerClient) return workerClient;
286
286
  if (typeof Worker === "undefined") return null;
287
- const { createSearchWorker } = await import("./worker-client-R6DBYPFT.js");
287
+ const { createSearchWorker } = await import("./worker-client-MPT7PNQ4.js");
288
288
  workerClient = createSearchWorker(config.workerUrl);
289
289
  return workerClient;
290
290
  }
@@ -427,7 +427,7 @@ var VelinSearch = class extends HTMLElement {
427
427
  return;
428
428
  }
429
429
  if (!this._indexLoaded) await this._loadIndex();
430
- const { groups } = this._search.query(q, {
430
+ const { groups } = await this._search.query(q, {
431
431
  minChars: this.minChars,
432
432
  fuzzy: this.fuzzy,
433
433
  categories: this.categories || void 0,