@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.
- package/README.de.md +87 -162
- package/README.md +188 -119
- package/cli/blueprint.js +98 -5
- package/cli/blueprints/app-chrome.html +18 -0
- package/cli/blueprints/benefits-grid.html +9 -0
- package/cli/blueprints/bottom-nav-mobile.html +2 -1
- package/cli/blueprints/cookie-consent.html +1 -1
- package/cli/blueprints/cta-band.html +6 -0
- package/cli/blueprints/faq-section.html +18 -0
- package/cli/blueprints/filter-bar.html +4 -4
- package/cli/blueprints/form-contact.html +6 -5
- package/cli/blueprints/hero-section.html +3 -3
- package/cli/blueprints/notification-center.html +1 -1
- package/cli/blueprints/onboarding.html +2 -1
- package/cli/blueprints/ops-console.html +29 -0
- package/cli/blueprints/pricing-band.html +37 -0
- package/cli/blueprints/process-steps.html +10 -0
- package/cli/blueprints/services-grid.html +9 -0
- package/cli/blueprints/settings-panel.html +8 -6
- package/cli/blueprints/split-hero.html +25 -0
- package/cli/blueprints/testimonials.html +8 -0
- package/cli/blueprints/trust-bar.html +10 -0
- package/cli/cli-manifest.json +81 -17
- package/cli/contrast-utils.js +97 -0
- package/cli/create.js +370 -0
- package/cli/docgen/extract-attributes.js +126 -10
- package/cli/docgen/extract-cli.js +3 -2
- package/cli/docgen/extract-components.js +61 -2
- package/cli/docgen/extract-utilities.js +10 -10
- package/cli/doctor.js +119 -0
- package/cli/index.js +531 -44
- package/cli/meta.js +84 -1
- package/cli/perf-audit.js +15 -2
- package/cli/prompt-engine.js +243 -0
- package/cli/review.js +268 -0
- package/cli/scaffold.js +119 -4
- package/cli/scanner-rules-data.js +7 -0
- package/cli/scanner.js +357 -4
- package/cli/serve.js +81 -0
- package/cli/skills.js +223 -0
- package/cli/wc-api.js +89 -0
- package/cli/workflow.js +42 -0
- package/components/index.js +2 -0
- package/components/runtime/component-loaders.js +2 -0
- package/components/velin-accordion.js +62 -13
- package/components/velin-bottom-nav.js +10 -0
- package/components/velin-calendar.js +212 -0
- package/components/velin-command.js +18 -2
- package/components/velin-data-table.js +78 -1
- package/components/velin-dialog.js +4 -1
- package/components/velin-drawer.js +2 -4
- package/components/velin-file-dropzone.js +162 -0
- package/components/velin-icon.js +22 -1
- package/components/velin-lightbox.js +5 -3
- package/components/velin-modal.js +2 -4
- package/components/velin-search.js +1 -1
- package/components/velin-sheet.js +2 -4
- package/core/a11y/component-contracts.json +20 -3
- package/core/meta/build.js +125 -5
- package/core/meta/design-constraints/contact.json +9 -0
- package/core/meta/design-constraints/faq.json +9 -0
- package/core/meta/design-constraints/hero.json +13 -0
- package/core/meta/knowledge/components.json +622 -0
- package/core/meta/knowledge/tokens.json +282 -0
- package/core/meta/pages/registry.json +294 -0
- package/core/meta/schema.js +3 -1
- package/core/meta/sections/registry.json +185 -0
- package/dist/chunks/{attributes-STYCS3O5.js → attributes-A423NX5J.js} +3 -3
- package/dist/chunks/{attributes-353XDOAX.js → attributes-F6UPIEVP.js} +1 -1
- package/dist/chunks/{attributes-ADOKLKA7.js → attributes-GLYXGGAL.js} +3 -3
- package/dist/chunks/{attributes-TPANLMLF.js → attributes-UFTYOSAU.js} +3 -3
- package/dist/chunks/attributes-XGLXLR2T.js +391 -0
- package/dist/chunks/attributes-YF4NI2QS.js +391 -0
- package/dist/chunks/browser-AUABBYUK.js +1544 -0
- package/dist/chunks/{chunk-RSMRR27R.js → chunk-2LSKX57P.js} +12 -10
- package/dist/chunks/{chunk-IEHKRARD.js → chunk-2TGCVDUL.js} +11 -9
- package/dist/chunks/{chunk-SRL6EWHP.js → chunk-5JWGUAPC.js} +17 -13
- package/dist/chunks/chunk-7YSO2OQ2.js +113 -0
- package/dist/chunks/{chunk-QVHYL3R4.js → chunk-BHR3ZG6U.js} +6 -6
- package/dist/chunks/{chunk-J472ERN2.js → chunk-JMSIHEYX.js} +15 -4
- package/dist/chunks/{chunk-MKZP2TBH.js → chunk-L7ZGUU4D.js} +2 -2
- package/dist/chunks/chunk-TUGIPKW5.js +113 -0
- package/dist/chunks/{highlight-GJHHV4KM.js → highlight-M2ELQNYK.js} +1 -1
- package/dist/chunks/runtime-entry.js +1 -1
- package/dist/chunks/{velin-accordion-FBIPAEXG.js → velin-accordion-WSY6BMLA.js} +64 -10
- package/dist/chunks/{velin-bottom-nav-7GEMPIM6.js → velin-bottom-nav-5RVRNGIP.js} +25 -0
- package/dist/chunks/{velin-bottom-nav-N3DFQR66.js → velin-bottom-nav-N5F4UO2I.js} +26 -1
- package/dist/chunks/velin-calendar-OFE6THUD.js +210 -0
- package/dist/chunks/velin-calendar-PGVNJTXK.js +217 -0
- package/dist/chunks/velin-calendar-XC7JRDSH.js +217 -0
- package/dist/chunks/{velin-code-block-CIAURDRJ.js → velin-code-block-ZGWG7JI5.js} +1 -1
- package/dist/chunks/{velin-combobox-NXS4QB4R.js → velin-combobox-56V2ZWT5.js} +1 -1
- package/dist/chunks/{velin-command-ONKO2A3J.js → velin-command-2HO2EKR6.js} +29 -2
- package/dist/chunks/{velin-command-TMLSRGIU.js → velin-command-ZJSLPK7B.js} +30 -3
- package/dist/chunks/{velin-copy-NYDBOKXT.js → velin-copy-XDQSV2XU.js} +1 -1
- package/dist/chunks/{velin-countdown-4ZVDGK4R.js → velin-countdown-V4Z5MA63.js} +1 -1
- package/dist/chunks/velin-data-table-UVR42UUM.js +372 -0
- package/dist/chunks/{velin-dialog-GTTZI564.js → velin-dialog-3YK2RPRV.js} +9 -2
- package/dist/chunks/{velin-dialog-ELFOZIXZ.js → velin-dialog-S24KAP4S.js} +3 -1
- package/dist/chunks/{velin-drawer-BE6TYN3H.js → velin-drawer-5PNU624J.js} +2 -4
- package/dist/chunks/{velin-drawer-DLL2GLT6.js → velin-drawer-CCM6S25D.js} +3 -5
- package/dist/chunks/{velin-email-RBX6ZR4S.js → velin-email-TNFONXPW.js} +1 -1
- package/dist/chunks/velin-file-dropzone-QRGF2JNA.js +154 -0
- package/dist/chunks/velin-file-dropzone-XIZMJ3NB.js +154 -0
- package/dist/chunks/{velin-icon-7M76DOPB.js → velin-icon-A6NCXGUK.js} +59 -17
- package/dist/chunks/{velin-icon-ZTSKUOVN.js → velin-icon-EC4B5XCM.js} +18 -5
- package/dist/chunks/{velin-lightbox-6E7CAATP.js → velin-lightbox-FFK4TUUP.js} +7 -6
- package/dist/chunks/{velin-lightbox-NXA3U2FM.js → velin-lightbox-P725FLTY.js} +5 -4
- package/dist/chunks/{velin-menubar-J66JXRWW.js → velin-menubar-6I2LM5HL.js} +1 -1
- package/dist/chunks/{velin-modal-5HYNNNUI.js → velin-modal-ICTMGRSU.js} +7 -8
- package/dist/chunks/{velin-modal-AEOTZ67O.js → velin-modal-JBNODH7D.js} +2 -4
- package/dist/chunks/{velin-popover-T72HK3DF.js → velin-popover-WZG2GHBL.js} +25 -4
- package/dist/chunks/{velin-rating-N4DI2XNL.js → velin-rating-QBBYRRBU.js} +1 -1
- package/dist/chunks/{velin-search-7B4KJ6TX.js → velin-search-B3L6J2RP.js} +2 -2
- package/dist/chunks/{velin-search-2XRQFBCS.js → velin-search-L3UG6NDQ.js} +5 -4
- package/dist/chunks/{velin-secure-field-6PV7RZDJ.js → velin-secure-field-DGYMP7OK.js} +1 -1
- package/dist/chunks/{velin-segmented-control-GYD5BIXQ.js → velin-segmented-control-P74GJPAR.js} +1 -1
- package/dist/chunks/{velin-sheet-R2Y67X6H.js → velin-sheet-M5GZZD7G.js} +2 -4
- package/dist/chunks/{velin-sheet-OUK6572T.js → velin-sheet-X7RXIWKV.js} +3 -5
- package/dist/chunks/{velin-stepper-X54WGHDG.js → velin-stepper-4YQJUHPC.js} +12 -5
- package/dist/chunks/{velin-toast-OMMOA2DK.js → velin-toast-UG5LWTG2.js} +5 -1
- package/dist/chunks/{velin-tooltip-BDHGRTQB.js → velin-tooltip-ZDH5SDLU.js} +1 -1
- package/dist/llms.txt +29 -7
- package/dist/search-index.json +156 -10
- package/dist/velin-agent.json +3973 -28
- package/dist/velinstyle-components.iife.js +1211 -284
- package/dist/velinstyle-components.js +1213 -284
- package/dist/velinstyle-components.min.js +266 -118
- package/dist/velinstyle.css +252 -67
- package/dist/velinstyle.d.ts +2 -0
- package/dist/velinstyle.min.css +1 -1
- package/package.json +20 -6
- package/packages/skill-engine/README.md +24 -0
- package/packages/skill-engine/package.json +7 -0
- package/packages/skill-engine/src/catalog.js +29 -0
- package/packages/skill-engine/src/index.js +5 -0
- package/packages/skill-engine/src/install.js +69 -0
- package/packages/skill-engine/src/registry.js +27 -0
- package/packages/skill-engine/src/resolve.js +68 -0
- package/packages/skill-engine/src/validate.js +40 -0
- package/packages/velinstyle-skills/README.md +6 -0
- package/packages/velinstyle-skills/adapter.json +8 -0
- package/packages/velinstyle-skills/bundles/landing-starter.bundle.yaml +12 -0
- package/packages/velinstyle-skills/bundles/review-suite.bundle.yaml +11 -0
- package/packages/velinstyle-skills/catalog.json +1004 -0
- package/packages/velinstyle-skills/graphs/component-ship.graph.yaml +14 -0
- package/packages/velinstyle-skills/graphs/landingpage.graph.yaml +21 -0
- package/packages/velinstyle-skills/graphs/release-gate.graph.yaml +15 -0
- package/packages/velinstyle-skills/index.js +22 -0
- package/packages/velinstyle-skills/package.json +7 -0
- package/packages/velinstyle-skills/packs/accessibility.pack.yaml +9 -0
- package/packages/velinstyle-skills/packs/design.pack.yaml +10 -0
- package/packages/velinstyle-skills/packs/documentation.pack.yaml +8 -0
- package/packages/velinstyle-skills/packs/enterprise.pack.yaml +10 -0
- package/packages/velinstyle-skills/packs/frontend.pack.yaml +10 -0
- package/packages/velinstyle-skills/packs/review.pack.yaml +9 -0
- package/packages/velinstyle-skills/projects/admin-panel.project.yaml +12 -0
- package/packages/velinstyle-skills/projects/blog.project.yaml +11 -0
- package/packages/velinstyle-skills/projects/documentation-portal.project.yaml +13 -0
- package/packages/velinstyle-skills/projects/ecommerce-shop.project.yaml +12 -0
- package/packages/velinstyle-skills/projects/landing-page.project.yaml +12 -0
- package/packages/velinstyle-skills/projects/laravel-dashboard.project.yaml +12 -0
- package/packages/velinstyle-skills/projects/marketing-website.project.yaml +14 -0
- package/packages/velinstyle-skills/projects/portfolio.project.yaml +12 -0
- package/packages/velinstyle-skills/registry.json +142 -0
- package/packages/velinstyle-skills/scripts/generate-assets.mjs +163 -0
- package/packages/velinstyle-skills/skills/velin-a11y-focus-keyboard/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-a11y-page-checklist/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-a11y-scan-fix/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-ai-agent-briefing/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-ai-plan-scaffold-review/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-ai-skill-authoring/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-components-accessibility-map/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-components-api-contract/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-components-recipe/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-components-select-compose/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-design-hero-compose/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-design-section-rhythm/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-design-surface-roles/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-dev-component-wire/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-dev-page-scaffold/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-dev-plan-first/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-docs-component-guide/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-docs-generate-api/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-dx-doctor-setup/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-dx-project-init/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-migration-legacy-wc/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-migration-prefix-classes/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-motion-reduced-safe/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-motion-reveal-feedback/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-perf-audit-fix/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-perf-runtime-tree-shake/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-release-changelog-sync/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-release-meta-rebuild/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-review-conversion-hero/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-review-page-gate/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-review-seo-meta/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-security-sanitize-html/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-security-scan-pii/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-testing-a11y-suite/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-testing-visual-smoke/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-themes-apply-token/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-themes-contrast-check/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-utilities-layout-apply/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-utilities-prefix-fix/SKILL.md +57 -0
- package/packages/velinstyle-skills/skills/velin-utilities-token-map/SKILL.md +57 -0
- package/packages/velinstyle-skills/templates/admin-panel.template.yaml +12 -0
- package/packages/velinstyle-skills/templates/blog.template.yaml +12 -0
- package/packages/velinstyle-skills/templates/documentation-portal.template.yaml +12 -0
- package/packages/velinstyle-skills/templates/ecommerce-shop.template.yaml +13 -0
- package/packages/velinstyle-skills/templates/landing-page.template.yaml +12 -0
- package/packages/velinstyle-skills/templates/laravel-dashboard.template.yaml +11 -0
- package/packages/velinstyle-skills/templates/marketing-website.template.yaml +13 -0
- package/packages/velinstyle-skills/templates/portfolio.template.yaml +12 -0
- package/schemas/component-knowledge.schema.json +33 -0
- package/schemas/design-constraint.schema.json +15 -0
- package/schemas/design-intelligence.schema.json +19 -0
- package/schemas/design-rule.schema.json +19 -0
- package/schemas/page-template.schema.json +24 -0
- package/schemas/review-report.schema.json +36 -0
- package/schemas/section.schema.json +22 -0
- package/schemas/skill-bundle.schema.json +15 -0
- package/schemas/skill-graph.schema.json +25 -0
- package/schemas/skill-pack.schema.json +14 -0
- package/schemas/skill-project.schema.json +16 -0
- package/schemas/skill-record.schema.json +27 -0
- package/schemas/skill-registry.schema.json +17 -0
- package/schemas/skill-template.schema.json +17 -0
- package/schemas/token-graph.schema.json +27 -0
- package/schemas/utility.schema.json +166 -0
- package/src/components/alert.css +22 -1
- package/src/components/calendar-dropzone.css +5 -0
- package/src/layout/app-shell.css +33 -0
- package/src/tokens/shadow.css +13 -0
- package/src/utilities/border.css +2 -0
- package/src/utilities/display.css +1 -24
- package/src/utilities/responsive.css +16 -1
- package/src/utilities/spacing.css +32 -0
- package/src/velinstyle.css +2 -0
- package/dist/chunks/attributes-3BZLI7XF.js +0 -364
- package/dist/chunks/attributes-4N5JP4CG.js +0 -364
- package/dist/chunks/attributes-5Q2WXGRC.js +0 -374
- package/dist/chunks/attributes-AIR7SVLK.js +0 -364
- package/dist/chunks/attributes-BGRN5XZO.js +0 -364
- package/dist/chunks/attributes-BVSQAYLR.js +0 -364
- package/dist/chunks/attributes-CDYFUY7Y.js +0 -364
- package/dist/chunks/attributes-JMYJZBPE.js +0 -364
- package/dist/chunks/attributes-R5JY3X4O.js +0 -374
- package/dist/chunks/attributes-TNSPQTHX.js +0 -374
- package/dist/chunks/chunk-2354NEBP.js +0 -109
- package/dist/chunks/chunk-2VNA7G7S.js +0 -109
- package/dist/chunks/chunk-AQLRJSGG.js +0 -109
- package/dist/chunks/chunk-EWPSDMQT.js +0 -109
- package/dist/chunks/chunk-LA7264K4.js +0 -85
- package/dist/chunks/chunk-QTJJ3DPO.js +0 -109
- package/dist/chunks/chunk-RZQVWFHW.js +0 -109
- package/dist/chunks/chunk-U4XHMZ7D.js +0 -109
- package/dist/chunks/chunk-V5YIUA6G.js +0 -109
- package/dist/chunks/chunk-XIET2VSZ.js +0 -109
- package/dist/chunks/chunk-XYLJ2GCB.js +0 -205
- package/dist/chunks/chunk-ZPSPKUYD.js +0 -109
- package/dist/chunks/highlight-XTHRKBA3.js +0 -37
- package/dist/chunks/velin-bottom-nav-2N2TYWOF.js +0 -86
- package/dist/chunks/velin-carousel-Y5VCOABZ.js +0 -213
- package/dist/chunks/velin-code-block-ASUBTAQV.js +0 -119
- package/dist/chunks/velin-code-block-TSUKPY4C.js +0 -123
- package/dist/chunks/velin-code-block-Y6CM726Q.js +0 -119
- package/dist/chunks/velin-combobox-2KDTCQ7N.js +0 -155
- package/dist/chunks/velin-command-M7RNHUPR.js +0 -136
- package/dist/chunks/velin-copy-T5KDTDXP.js +0 -81
- package/dist/chunks/velin-countdown-5XSTN3BH.js +0 -101
- package/dist/chunks/velin-counter-ISCTEAHI.js +0 -118
- package/dist/chunks/velin-dialog-D2GUHSCD.js +0 -144
- package/dist/chunks/velin-dialog-IJLFDXAJ.js +0 -144
- package/dist/chunks/velin-dialog-TNS3WXMB.js +0 -144
- package/dist/chunks/velin-drawer-MJS6WCF7.js +0 -130
- package/dist/chunks/velin-email-N5B5ZYTE.js +0 -90
- package/dist/chunks/velin-icon-KZO3IEHG.js +0 -164
- package/dist/chunks/velin-lightbox-I75U6JF4.js +0 -140
- package/dist/chunks/velin-lightbox-QOTB4PRL.js +0 -140
- package/dist/chunks/velin-lightbox-UCD6N7HF.js +0 -140
- package/dist/chunks/velin-live-dot-XHUZCIDZ.js +0 -67
- package/dist/chunks/velin-menubar-SFEXJE56.js +0 -86
- package/dist/chunks/velin-modal-2HOBXE6F.js +0 -176
- package/dist/chunks/velin-modal-GLI2XZZB.js +0 -176
- package/dist/chunks/velin-popover-EXINRIGJ.js +0 -145
- package/dist/chunks/velin-popover-OXX7MRZ6.js +0 -145
- package/dist/chunks/velin-popover-YKCCROJG.js +0 -145
- package/dist/chunks/velin-rating-XRQJV4LO.js +0 -91
- package/dist/chunks/velin-scroll-top-F2FCZNYD.js +0 -58
- package/dist/chunks/velin-search-4YHJWYSS.js +0 -556
- package/dist/chunks/velin-search-LWHY23Q5.js +0 -474
- package/dist/chunks/velin-secure-field-H7FSBUJW.js +0 -95
- package/dist/chunks/velin-segmented-control-PQX6LKOJ.js +0 -109
- package/dist/chunks/velin-sheet-3OGI4HD7.js +0 -119
- package/dist/chunks/velin-sparkline-GVEANJVW.js +0 -184
- package/dist/chunks/velin-sparkline-KDA3GQAN.js +0 -162
- package/dist/chunks/velin-stepper-2ZIHLKGM.js +0 -141
- package/dist/chunks/velin-stepper-FYEUEWE6.js +0 -141
- package/dist/chunks/velin-stepper-wc-QU3KRVQR.js +0 -133
- package/dist/chunks/velin-theme-toggle-BNNS7WLV.js +0 -285
- package/dist/chunks/velin-theme-toggle-NO7V4TWI.js +0 -285
- package/dist/chunks/velin-theme-toggle-QELCJM2Q.js +0 -291
- package/dist/chunks/velin-toast-RCZ4CSUC.js +0 -109
- package/dist/chunks/velin-toast-WEUBTJG6.js +0 -109
- package/dist/chunks/velin-tooltip-664IOHZA.js +0 -112
- package/dist/chunks/velin-tooltip-wc-LXDVT6DE.js +0 -103
- 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-
|
|
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
|
|
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,
|
|
71
|
+
this._renderFromCDN(name, size, a11y, provider, variant);
|
|
58
72
|
return;
|
|
59
73
|
}
|
|
60
|
-
this._renderFromSprite(name, size,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
136
|
+
this._injectSVG(clean, size, a11y);
|
|
116
137
|
} catch {
|
|
117
|
-
this._renderFromSprite(name, size,
|
|
138
|
+
this._renderFromSprite(name, size, a11y);
|
|
118
139
|
}
|
|
119
140
|
}
|
|
120
|
-
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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"
|
|
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
|
|
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-
|
|
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();
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-42VVPW6N.js";
|
|
9
9
|
import {
|
|
10
10
|
escapeHTML
|
|
11
|
-
} from "./chunk-
|
|
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"
|
|
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">×</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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
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
|
|
70
|
-
|
|
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") {
|
|
@@ -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-
|
|
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,
|