bojuvue 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +287 -0
  3. package/dist/BVButton.test.d.ts +1 -0
  4. package/dist/BVButton.types.d.ts +9 -0
  5. package/dist/BVButton.vue.d.ts +15 -0
  6. package/dist/BVIconButton.test.d.ts +1 -0
  7. package/dist/BVIconButton.types.d.ts +11 -0
  8. package/dist/BVIconButton.vue.d.ts +17 -0
  9. package/dist/BVMoreButton.test.d.ts +1 -0
  10. package/dist/BVMoreButton.types.d.ts +15 -0
  11. package/dist/BVMoreButton.vue.d.ts +20 -0
  12. package/dist/BVPlatformButton.test.d.ts +1 -0
  13. package/dist/BVPlatformButton.types.d.ts +10 -0
  14. package/dist/BVPlatformButton.vue.d.ts +17 -0
  15. package/dist/bojuvue.css +2 -0
  16. package/dist/bojuvue.js +174 -0
  17. package/dist/index.d.ts +10 -0
  18. package/dist/moreButtonMenu.d.ts +9 -0
  19. package/dist/moreButtonMenu.test.d.ts +1 -0
  20. package/dist/platform.d.ts +22 -0
  21. package/dist/platform.test.d.ts +1 -0
  22. package/dist/url.d.ts +1 -0
  23. package/dist/useManifestFetch.d.ts +53 -0
  24. package/dist/useMoreButtonMenu-BdAgqGZv.js +194 -0
  25. package/dist/useMoreButtonMenu.d.ts +16 -0
  26. package/dist/vitepress/BVButton.test.d.ts +1 -0
  27. package/dist/vitepress/BVButton.vue.d.ts +12 -0
  28. package/dist/vitepress/BVIconButton.test.d.ts +1 -0
  29. package/dist/vitepress/BVIconButton.vue.d.ts +17 -0
  30. package/dist/vitepress/BVMoreButton.test.d.ts +1 -0
  31. package/dist/vitepress/BVMoreButton.vue.d.ts +20 -0
  32. package/dist/vitepress/BVPlatformButton.test.d.ts +1 -0
  33. package/dist/vitepress/BVPlatformButton.vue.d.ts +15 -0
  34. package/dist/vitepress.d.ts +10 -0
  35. package/dist/vitepress.js +223 -0
  36. package/package.json +65 -0
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Scott Kirvan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,287 @@
1
+ # BojuVue 보주뷰 [![starline](https://raw.githubusercontent.com/ScottKirvan/BojuVue/refs/heads/starlines/ScottKirvan/BojuVue/starline.svg)](https://github.com/qoomon/starlines)
2
+ <div align="center">
3
+
4
+ <img src="assets/media/logo.jpg" alt="logo" width="200" height="auto" />
5
+ <h1><a href="https://github.com/ScottKirvan/BojuVue">ScottKirvan/BojuVue</a></h1>
6
+ <h3>Shared Vue 3 components, with VitePress-aware builds</h3>
7
+
8
+
9
+ <!-- Badges -->
10
+ <p>
11
+ <a href="https://github.com/ScottKirvan/BojuVue/graphs/contributors">
12
+ <img src="https://img.shields.io/github/contributors/ScottKirvan/BojuVue" alt="contributors" />
13
+ </a>
14
+ <a href="https://github.com/ScottKirvan/BojuVue/commits/main">
15
+ <img src="https://img.shields.io/github/last-commit/ScottKirvan/BojuVue" alt="last update" />
16
+ </a>
17
+ <a href="https://github.com/ScottKirvan/BojuVue/network/members">
18
+ <img src="https://img.shields.io/github/forks/ScottKirvan/BojuVue" alt="forks" />
19
+ </a>
20
+ <a href="https://github.com/ScottKirvan/BojuVue/stargazers">
21
+ <img src="https://img.shields.io/github/stars/ScottKirvan/BojuVue" alt="stars" />
22
+ </a>
23
+ <a href="https://github.com/ScottKirvan/BojuVue/issues/">
24
+ <img src="https://img.shields.io/github/issues/ScottKirvan/BojuVue" alt="open issues" />
25
+ </a>
26
+ <a href="https://github.com/ScottKirvan/BojuVue/blob/main/LICENSE.md">
27
+ <img src="https://img.shields.io/github/license/ScottKirvan/BojuVue.svg" alt="license" />
28
+ </a>
29
+ <a href="https://discord.gg/TN6XJSNK5Y">
30
+ <!--<img src="https://img.shields.io/discord/704680098577514527?style=flat-square&label=%F0%9F%92%AC%20discord&color=00ACD7">-->
31
+ <img src="https://img.shields.io/discord/1052011377415438346?style=flat-square&label=discord&color=00ACD7">
32
+ </a>
33
+ </p>
34
+
35
+ <h4>
36
+ <a href="https://scottkirvan.github.io/BojuVue/">Documentation</a>
37
+ <span> · </span>
38
+ <a href="https://github.com/ScottKirvan/BojuVue/issues/new?template=bug_report.md">Report Bug</a>
39
+ <span> · </span>
40
+ <a href="https://github.com/ScottKirvan/BojuVue/issues/new?template=feature_request.md">Request Feature</a>
41
+ </h4>
42
+ </div>
43
+
44
+ **BojuVue** is a Vue 3 component library published to npm as [`@scottkirvan/bojuvue`](https://www.npmjs.com/package/@scottkirvan/bojuvue). It exists so that VitePress sites — this author's homepage blog and several local documentation sites — can share one set of landing-page and UX components instead of duplicating them per repo. Update this repo, bump the version, publish, and every consuming site can pull in the update with `npm update`.
45
+
46
+ Branches
47
+ --------
48
+ `main` is the [deployed](https://ScottKirvan.github.io/BojuVue/) branch. The repo doesn't currently contain any other historic or dev branches.
49
+
50
+ Repo Layout
51
+ -----------
52
+ ```
53
+ BojuVue
54
+ ├───.github
55
+ │ ├───gitignore-templates # .gitignore templates for other stacks (not used by this repo's own Node build)
56
+ │ ├───release-please # Release-Please config — automated version bumps + CHANGELOG from Conventional Commits
57
+ │ └───workflows # CI (test + build), docs deploy, release, pre-release staging
58
+ ├───assets
59
+ │ └───media # Logo
60
+ ├───docs # VitePress site — consumer-facing docs, deployed to GitHub Pages
61
+ ├───notes
62
+ │ ├───dev # Design specs and working notes for this repo's own contributors
63
+ │ ├───CHANGELOG.md # Auto-generated by Release-Please
64
+ │ ├───TODO.md
65
+ │ └───VERSION.md
66
+ ├───src # Library source — see Architecture below
67
+ ├───CLAUDE.md # AI agent context
68
+ ├───CODE_OF_CONDUCT.md # Community guidelines
69
+ ├───CONTRIBUTING.md # Contribution guidelines
70
+ ├───LICENSE.md # MIT License
71
+ └───README.md # This file
72
+ ```
73
+
74
+ Issue and PR templates aren't in this repo's own `.github/` — they're inherited from
75
+ the `ScottKirvan/.github` org repo via GitHub's community health file fallback.
76
+
77
+ Table of Contents
78
+ -----------------
79
+ - [Branches](#branches)
80
+ - [Repo Layout](#repo-layout)
81
+ - [Features](#features)
82
+ - [Architecture](#architecture)
83
+ - [Installation](#installation)
84
+ - [Usage](#usage)
85
+ - [Adding a new component](#adding-a-new-component)
86
+ - [Contributions / Contact](#contributions--contact)
87
+ - [Credits](#credits)
88
+
89
+ Features
90
+ --------
91
+ - Vue 3 + TypeScript components, built as an ES module via Vite library mode
92
+ - `vue` is a peer dependency, so consuming sites use their own Vue instance — no duplicate copies, no broken reactivity
93
+ - Every component is exported from one entry point (`src/index.ts`), so consuming a new component is a one-line import change
94
+ - The `docs/` VitePress site imports directly from `src/index.ts`/`src/vitepress.ts` and registers every exported component globally, so new components can be previewed live in a real VitePress site without publishing or `npm link`
95
+ - Some components (currently `BVPlatformButton`) ship as **two fully independent builds behind two import paths**: a generic implementation at `@scottkirvan/bojuvue`, with zero dependency on `vitepress`, and a VitePress-specific implementation at `@scottkirvan/bojuvue/vitepress`, same component name, resolving anything VitePress-specific for you. Neither component imports or renders the other — the import path is what disambiguates them. `vitepress` is an *optional* peer dependency — installing the package alone never requires it; only importing from the `/vitepress` path does.
96
+
97
+ Architecture
98
+ ------------
99
+ The bit that shapes everything else in this repo: **the generic build must have zero
100
+ dependency on `vitepress`, anywhere in its module graph.** Everything below exists to
101
+ make that hold under a real bundler, not just in theory.
102
+
103
+ **Two entry points, two physical files.** `vite.config.ts` builds library mode with two
104
+ separate entries — `src/index.ts` → `dist/bojuvue.js` (published as `.`) and
105
+ `src/vitepress.ts` → `dist/vitepress.js` (published as `./vitepress`). `src/vitepress.ts`
106
+ re-exports everything `src/index.ts` has, plus its own VitePress-specific component
107
+ implementations, under the same names. This has to be two genuinely separate output
108
+ files, not two exports of one bundle — if both compiled into a single file, importing
109
+ only the generic path would still execute a top-level `import 'vitepress'` somewhere in
110
+ it. Verify this invariant after touching anything under `src/` by building and grepping
111
+ the output:
112
+ ```sh
113
+ npm run build
114
+ grep -r vitepress dist/bojuvue.js # should print nothing
115
+ ```
116
+
117
+ **Two independent implementations per VitePress-aware component.** A component that
118
+ needs anything VitePress-specific (site data, the router, VitePress's own `VPButton`)
119
+ doesn't take a runtime "VitePress mode" flag — it gets two fully independent
120
+ implementations sharing one exported name, disambiguated by import path:
121
+ `src/ComponentName.vue` (plain props, no `vitepress` import, exported from
122
+ `src/index.ts`) and `src/vitepress/ComponentName.vue` (calls whatever VitePress
123
+ composables it needs itself, exported from `src/vitepress.ts`). Neither imports or
124
+ renders the other. `BVPlatformButton` is the worked example — see
125
+ `src/BVPlatformButton.vue` and `src/vitepress/BVPlatformButton.vue`. Logic genuinely
126
+ shared between the two (e.g. manifest-fetch orchestration) lives in a plain utility
127
+ module both call independently — see `src/useManifestFetch.ts` — not in one component
128
+ owning the other's rendering.
129
+
130
+ **Prop types stay inline in `defineProps<T>()`.** `@vue/compiler-sfc` resolving a
131
+ `defineProps<T>()` type imported from another module needs the `typescript` package
132
+ loadable from wherever the `.vue` file is compiled — which breaks under `docs/`'s
133
+ cross-directory source build (next point) whenever the repo root's `node_modules` isn't
134
+ present. Keep the type written out inline in the macro itself. A type used only for a
135
+ public, non-macro export (`BVPlatformButtonProps` in `src/BVPlatformButton.types.ts`,
136
+ for instance) is fine to keep in its own file — the constraint is specifically about the
137
+ `defineProps<T>()` type position.
138
+
139
+ **Real logic lives outside the `.vue` file.** Components with real logic — detection,
140
+ data-shaping, anything beyond pure rendering — extract that logic into a plain `.ts`
141
+ module (`src/platform.ts` next to `BVPlatformButton.vue`) rather than keeping it inline
142
+ in `<script setup>`. Much easier to unit test a plain function than to mount a component
143
+ or mock Vue-specific APIs to exercise the same branch.
144
+
145
+ **`docs/` previews live source, not the published package.** `docs/` is a separate,
146
+ independently-installed VitePress project. `docs/.vitepress/theme/index.ts` imports
147
+ directly from `../../../src/vitepress` — this repo's own VitePress-entry *source* — and
148
+ registers every export globally, so a new component shows up in a real VitePress site
149
+ the moment you write it (`npm run docs:dev`), no publish or `npm link` needed. That
150
+ import crosses a directory boundary `docs/`'s own dependency resolution doesn't know
151
+ about: files under repo-root `src/` still `import 'vue'`/`import 'vitepress'`
152
+ themselves, which would otherwise resolve relative to `src/`'s own location. A scoped
153
+ Vite plugin in `docs/.vitepress/config.mts` fixes this by redirecting any such import,
154
+ when the importing file is physically under repo-root `src/`, through Vite's normal
155
+ resolver as if it came from inside `docs/` instead. Verify a change here by temporarily
156
+ renaming the repo root's `node_modules` out of the way and confirming `npm run
157
+ docs:build` (from `docs/`) still succeeds — `docs/`'s deploy job never installs the repo
158
+ root's dependencies, so this has to work without them.
159
+
160
+ **Typechecking and build.** `npm run build` runs `vue-tsc -b` (typecheck, via composite
161
+ TypeScript project references) then `vite build` (emits `dist/`). There's no separate
162
+ typecheck-only script — `vue-tsc -b --noEmit` isn't valid with composite project
163
+ references, so `build` is the only way to typecheck the library.
164
+
165
+ Installation
166
+ ------------
167
+ ```
168
+ npm install @scottkirvan/bojuvue
169
+ ```
170
+
171
+ Usage
172
+ -----
173
+ Register components however you already register components in your app:
174
+
175
+ ```ts
176
+ // main.ts (or wherever you create your Vue app)
177
+ import { createApp } from 'vue'
178
+ import { BVPlatformButton, SomeComponent } from '@scottkirvan/bojuvue'
179
+ import App from './App.vue'
180
+
181
+ const app = createApp(App)
182
+ app.component('BVPlatformButton', BVPlatformButton)
183
+ app.component('SomeComponent', SomeComponent)
184
+ app.mount('#app')
185
+ ```
186
+
187
+ Building a VitePress site? Register the same way from `enhanceApp` in
188
+ `.vitepress/theme/index.ts` instead of `main.ts`, and prefer importing from
189
+ `@scottkirvan/bojuvue/vitepress` for any component with a VitePress-aware build (see
190
+ Features above):
191
+
192
+ ```ts
193
+ import DefaultTheme from 'vitepress/theme'
194
+ import { BVPlatformButton } from '@scottkirvan/bojuvue/vitepress'
195
+ import { SomeComponent } from '@scottkirvan/bojuvue'
196
+
197
+ export default {
198
+ extends: DefaultTheme,
199
+ enhanceApp({ app }) {
200
+ app.component('BVPlatformButton', BVPlatformButton)
201
+ app.component('SomeComponent', SomeComponent)
202
+ },
203
+ }
204
+ ```
205
+
206
+ Then use it in any `.md` page. Update later with `npm update`.
207
+
208
+ See the **[component reference](https://scottkirvan.github.io/BojuVue/components/)**
209
+ for every available component's props and a usage example — including, per component,
210
+ which import path(s) it's available from.
211
+
212
+ Adding a new component
213
+ -----------------------
214
+ Read [Architecture](#architecture) first if you haven't — the steps below assume you
215
+ know why some components have two implementations and why prop types stay inline.
216
+
217
+ **A component with no VitePress-specific needs:**
218
+
219
+ 1. Write the `.vue` file under `src/` (e.g. `src/YourComponent.vue`) — standard SFC:
220
+ `<script setup lang="ts">` for props/logic, `<template>` for markup, `<style
221
+ scoped>` for CSS scoped to that component alone.
222
+ 2. Make configurable text/behavior actual props, not hardcoded strings —
223
+ `defineProps<{...}>()` with `withDefaults(...)` for sensible fallbacks. Keep the prop
224
+ type written inline in the macro.
225
+ 3. Extract any real logic (detection, data-shaping) into a plain `.ts` module next to
226
+ the component, and write unit tests for it (see `src/platform.ts` /
227
+ `src/platform.test.ts`).
228
+ 4. Add one line to `src/index.ts`: `export { default as YourComponent } from
229
+ './YourComponent.vue'`.
230
+ 5. Preview it: `npm run docs:dev` (from `docs/`), then use `<YourComponent />` anywhere
231
+ in a `.md` file — it's registered globally in this repo's own `docs/` theme, so no
232
+ import is needed there.
233
+ 6. Add a reference page at `docs/components/your-component.md` (props table + usage
234
+ example — copy the structure of an existing page) and link it from
235
+ `docs/components/index.md` and the sidebar in `docs/.vitepress/config.mts`.
236
+ 7. `npm run build` at the repo root to confirm the library itself still builds clean,
237
+ and `npm test` to run the unit suite.
238
+
239
+ **A component that needs something VitePress-specific** (worked example:
240
+ `BVPlatformButton`) gets two fully independent implementations instead of one file:
241
+
242
+ 1. The framework-agnostic logic and markup goes in `src/YourComponent.vue` — plain
243
+ props in (including anything the VitePress-specific implementation would otherwise
244
+ read from a VitePress composable — e.g. a `base` prop standing in for
245
+ `useData().site.value.base`, resolved by that other implementation itself, not read
246
+ directly here). No `vitepress` import anywhere in this file.
247
+ 2. `src/vitepress/YourComponent.vue` calls whatever VitePress composables it needs
248
+ itself and implements its own rendering. It does not import or render
249
+ `src/YourComponent.vue`. Any logic genuinely shared between the two (like fetch
250
+ orchestration — see `useManifestFetch`) lives in a plain utility module both call
251
+ independently, not in one component owning the other's rendering.
252
+ 3. `src/index.ts` exports the generic implementation; `src/vitepress.ts` re-exports
253
+ everything `src/index.ts` has, plus exports the VitePress-specific implementation —
254
+ both under the same name, `YourComponent`. The import path is what disambiguates
255
+ them.
256
+ 4. Preview via `docs/.vitepress/theme/index.ts`, which registers from `src/vitepress.ts`
257
+ (the superset) — this exercises both the VitePress-specific implementation and
258
+ everything re-exported from the generic one.
259
+ 5. `npm run build` must still produce two separate physical files (check
260
+ `vite.config.ts`'s `build.lib.entry`), and the generic build's output file must
261
+ contain zero reference to `vitepress` — grep for it directly after any build that
262
+ touches this component (see [Architecture](#architecture)).
263
+ 6. Add the reference page and sidebar entry as in step 6 above, and document both import
264
+ paths on that page — see `docs/components/platform-button.md` for the pattern.
265
+
266
+ **Before opening a pull request:** `npm test` and `npm run build` both pass; tests exist
267
+ for anything with real logic; every failure and edge path has a deliberate, documented
268
+ user-visible behavior; the reference page documents every prop's default and whether
269
+ it's required, and calls out anything deliberately not supported, with why. See
270
+ `CLAUDE.md` for the full set of engineering conventions this project holds
271
+ contributions to.
272
+
273
+ Contributions / Contact
274
+ -----------------------
275
+ - Please [file an issue](https://github.com/ScottKirvan/BojuVue/issues/new), or [grab a fork](https://github.com/ScottKirvan/BojuVue/fork), hack away, and submit a [pull request](https://github.com/ScottKirvan/BojuVue/pulls).
276
+ - Contact me at [linkedin.com/in/scottkirvan/](https://www.linkedin.com/in/scottkirvan/)
277
+ - You can also contact me at my [discord](https://discord.gg/TN6XJSNK5Y) server, I'm cptvideo.
278
+
279
+ Credits
280
+ -------
281
+ **BojuVue** — Copyright (c) 2026 [Scott Kirvan](https://github.com/ScottKirvan). [MIT License](LICENSE.md).
282
+
283
+ Scaffolded from [ScooterGitTemplate](https://github.com/ScottKirvan/ScooterGitTemplate).
284
+
285
+ Project Link: [BojuVue](https://github.com/ScottKirvan/BojuVue)
286
+ [CHANGELOG](notes/CHANGELOG.md)
287
+ [TODO](notes/TODO.md)
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ export interface BVButtonProps {
2
+ text: string;
3
+ href?: string;
4
+ target?: string;
5
+ rel?: string;
6
+ size?: 'medium' | 'big';
7
+ theme?: 'brand' | 'alt' | 'sponsor';
8
+ tag?: string;
9
+ }
@@ -0,0 +1,15 @@
1
+ type __VLS_Props = {
2
+ text: string;
3
+ href?: string;
4
+ target?: string;
5
+ rel?: string;
6
+ size?: 'medium' | 'big';
7
+ theme?: 'brand' | 'alt' | 'sponsor';
8
+ tag?: string;
9
+ };
10
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
11
+ size: "medium" | "big";
12
+ theme: "brand" | "alt" | "sponsor";
13
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ export interface BVIconButtonProps {
2
+ text?: string;
3
+ href?: string;
4
+ target?: string;
5
+ rel?: string;
6
+ size?: 'medium' | 'big';
7
+ theme?: 'brand' | 'alt' | 'sponsor';
8
+ tag?: string;
9
+ icon?: string;
10
+ label?: string;
11
+ }
@@ -0,0 +1,17 @@
1
+ type __VLS_Props = {
2
+ text?: string;
3
+ href?: string;
4
+ target?: string;
5
+ rel?: string;
6
+ size?: 'medium' | 'big';
7
+ theme?: 'brand' | 'alt' | 'sponsor';
8
+ tag?: string;
9
+ icon?: string;
10
+ label?: string;
11
+ };
12
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
13
+ size: "medium" | "big";
14
+ theme: "brand" | "alt" | "sponsor";
15
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ export interface BVMoreButtonItem {
2
+ label: string;
3
+ href: string;
4
+ icon?: string;
5
+ target?: string;
6
+ rel?: string;
7
+ }
8
+ export interface BVMoreButtonProps {
9
+ items: BVMoreButtonItem[];
10
+ icon?: string;
11
+ text?: string;
12
+ label?: string;
13
+ size?: 'medium' | 'big';
14
+ theme?: 'brand' | 'alt' | 'sponsor';
15
+ }
@@ -0,0 +1,20 @@
1
+ type __VLS_Props = {
2
+ items: {
3
+ label: string;
4
+ href: string;
5
+ icon?: string;
6
+ target?: string;
7
+ rel?: string;
8
+ }[];
9
+ icon?: string;
10
+ text?: string;
11
+ label?: string;
12
+ size?: 'medium' | 'big';
13
+ theme?: 'brand' | 'alt' | 'sponsor';
14
+ };
15
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
16
+ text: string;
17
+ label: string;
18
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
19
+ declare const _default: typeof __VLS_export;
20
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ export interface BVPlatformButtonProps {
2
+ manifestUrl?: string;
3
+ fallbackHref?: string;
4
+ fallbackLabel?: string;
5
+ size?: 'medium' | 'big';
6
+ theme?: 'brand' | 'alt' | 'sponsor';
7
+ target?: string;
8
+ rel?: string;
9
+ icon?: string;
10
+ }
@@ -0,0 +1,17 @@
1
+ type __VLS_Props = {
2
+ manifestUrl?: string;
3
+ fallbackHref?: string;
4
+ fallbackLabel?: string;
5
+ size?: 'medium' | 'big';
6
+ theme?: 'brand' | 'alt' | 'sponsor';
7
+ target?: string;
8
+ rel?: string;
9
+ icon?: string;
10
+ base?: string;
11
+ };
12
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
13
+ base: string;
14
+ manifestUrl: string;
15
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
@@ -0,0 +1,2 @@
1
+ .bv-button[data-v-8e3f769d]{text-align:center;white-space:nowrap;border:1px solid #0000;font-weight:600;text-decoration:none;transition:color .25s,border-color .25s,background-color .25s;display:inline-block}.bv-button[data-v-8e3f769d]:active{transition:color .1s,border-color .1s,background-color .1s}.bv-button.medium[data-v-8e3f769d]{border-radius:20px;padding:0 20px;font-size:14px;line-height:38px}.bv-button.big[data-v-8e3f769d]{border-radius:24px;padding:0 24px;font-size:16px;line-height:46px}.bv-button.brand[data-v-8e3f769d]{border-color:var(--vp-button-brand-border,#3c8772);color:var(--vp-button-brand-text,#fff);background-color:var(--vp-button-brand-bg,#3c8772)}.bv-button.brand[data-v-8e3f769d]:hover{border-color:var(--vp-button-brand-hover-border,#359469);color:var(--vp-button-brand-hover-text,#fff);background-color:var(--vp-button-brand-hover-bg,#359469)}.bv-button.brand[data-v-8e3f769d]:active{border-color:var(--vp-button-brand-active-border,#2b8760);color:var(--vp-button-brand-active-text,#fff);background-color:var(--vp-button-brand-active-bg,#2b8760)}.bv-button.alt[data-v-8e3f769d]{border-color:var(--vp-button-alt-border,transparent);color:var(--vp-button-alt-text,#3c3c43);background-color:var(--vp-button-alt-bg,#f2f2f3)}.bv-button.alt[data-v-8e3f769d]:hover{border-color:var(--vp-button-alt-hover-border,transparent);color:var(--vp-button-alt-hover-text,#3c3c43);background-color:var(--vp-button-alt-hover-bg,#e6e6e7)}.bv-button.alt[data-v-8e3f769d]:active{border-color:var(--vp-button-alt-active-border,transparent);color:var(--vp-button-alt-active-text,#3c3c43);background-color:var(--vp-button-alt-active-bg,#dcdcdd)}.bv-button.sponsor[data-v-8e3f769d]{border-color:var(--vp-button-sponsor-border,transparent);color:var(--vp-button-sponsor-text,#d5389c);background-color:var(--vp-button-sponsor-bg,transparent)}.bv-button.sponsor[data-v-8e3f769d]:hover{border-color:var(--vp-button-sponsor-hover-border,#d5389c);color:var(--vp-button-sponsor-hover-text,#d5389c);background-color:var(--vp-button-sponsor-hover-bg,transparent)}.bv-button.sponsor[data-v-8e3f769d]:active{border-color:var(--vp-button-sponsor-active-border,#d5389c);color:var(--vp-button-sponsor-active-text,#d5389c);background-color:var(--vp-button-sponsor-active-bg,transparent)}.bv-icon-button[data-v-6c0ea7e4]{align-items:center;display:inline-flex;position:relative}.bv-icon-button-icon[data-v-6c0ea7e4]{pointer-events:none;justify-content:center;align-items:center;display:inline-flex;position:absolute}.bv-icon-button-icon[data-v-6c0ea7e4] svg{width:1em;height:1em}.bv-icon-button.icon-only .bv-icon-button-icon[data-v-6c0ea7e4]{inset:0}.bv-icon-button.has-icon .bv-icon-button-icon[data-v-6c0ea7e4]{top:50%;transform:translateY(-50%)}.bv-icon-button.has-icon.medium .bv-icon-button-icon[data-v-6c0ea7e4]{font-size:14px;left:20px}.bv-icon-button.has-icon.big .bv-icon-button-icon[data-v-6c0ea7e4]{font-size:16px;left:24px}[data-v-6c0ea7e4] .bv-button.icon-only{padding:0;line-height:1}[data-v-6c0ea7e4] .bv-button.icon-only.medium{width:38px;height:38px}[data-v-6c0ea7e4] .bv-button.icon-only.big{width:46px;height:46px}[data-v-6c0ea7e4] .bv-button.has-icon.medium{padding-left:calc(26px + 1em)}[data-v-6c0ea7e4] .bv-button.has-icon.big{padding-left:calc(30px + 1em)}.bv-more-button[data-v-f229a206]{display:inline-flex;position:relative}.bv-more-button-panel[data-v-f229a206]{z-index:100;border:1px solid var(--vp-c-divider,#e2e2e3);background-color:var(--vp-c-bg-elv,#fff);min-width:180px;box-shadow:var(--vp-shadow-3,0 12px 32px #0000002e);border-radius:8px;flex-direction:column;padding:4px;display:flex;position:fixed}.bv-more-button-item[data-v-f229a206]{color:var(--vp-c-text-1,#3c3c43);white-space:nowrap;border-radius:6px;align-items:center;gap:8px;padding:8px 12px;font-size:14px;text-decoration:none;display:flex}.bv-more-button-item[data-v-f229a206]:hover,.bv-more-button-item[data-v-f229a206]:focus-visible{background-color:var(--vp-c-default-soft,#f2f2f3);outline:none}.bv-more-button-item-icon[data-v-f229a206] svg{width:1em;height:1em}.VPButton[data-v-7730de16]{text-decoration:none}.bv-icon-button[data-v-27cc1a4c]{align-items:center;display:inline-flex;position:relative}.bv-icon-button-icon[data-v-27cc1a4c]{pointer-events:none;justify-content:center;align-items:center;display:inline-flex;position:absolute}.bv-icon-button-icon[data-v-27cc1a4c] svg{width:1em;height:1em}.bv-icon-button.icon-only .bv-icon-button-icon[data-v-27cc1a4c]{inset:0}.bv-icon-button.has-icon .bv-icon-button-icon[data-v-27cc1a4c]{top:50%;transform:translateY(-50%)}.bv-icon-button.has-icon.medium .bv-icon-button-icon[data-v-27cc1a4c]{font-size:14px;left:20px}.bv-icon-button.has-icon.big .bv-icon-button-icon[data-v-27cc1a4c]{font-size:16px;left:24px}[data-v-27cc1a4c] .bv-button.icon-only{padding:0;line-height:1}[data-v-27cc1a4c] .bv-button.icon-only.medium{width:38px;height:38px}[data-v-27cc1a4c] .bv-button.icon-only.big{width:46px;height:46px}[data-v-27cc1a4c] .VPButton.has-icon.medium{padding-left:calc(26px + 1em)}[data-v-27cc1a4c] .VPButton.has-icon.big{padding-left:calc(30px + 1em)}.bv-more-button[data-v-e689232f]{display:inline-flex;position:relative}.bv-more-button-panel[data-v-e689232f]{z-index:100;border:1px solid var(--vp-c-divider);background-color:var(--vp-c-bg-elv);min-width:180px;box-shadow:var(--vp-shadow-3);border-radius:8px;flex-direction:column;padding:4px;display:flex;position:fixed}.bv-more-button-item[data-v-e689232f]{color:var(--vp-c-text-1);white-space:nowrap;border-radius:6px;align-items:center;gap:8px;padding:8px 12px;font-size:14px;text-decoration:none;display:flex}.bv-more-button-item[data-v-e689232f]:hover,.bv-more-button-item[data-v-e689232f]:focus-visible{background-color:var(--vp-c-default-soft);outline:none}.bv-more-button-item-icon[data-v-e689232f] svg{width:1em;height:1em}
2
+ /*$vite$:1*/
@@ -0,0 +1,174 @@
1
+ import { a as e, c as t, i as n, l as r, n as i, o as a, r as o, s, t as c } from "./useMoreButtonMenu-BdAgqGZv.js";
2
+ import { Fragment as l, computed as u, createBlock as d, createCommentVNode as f, createElementBlock as p, createTextVNode as m, createVNode as h, defineComponent as g, mergeProps as _, normalizeClass as v, normalizeStyle as y, onMounted as b, openBlock as x, ref as S, renderList as C, toDisplayString as w, unref as T } from "vue";
3
+ //#region src/BVIconButton.vue?vue&type=script&setup=true&lang.ts
4
+ var E = ["innerHTML"], D = /*#__PURE__*/ t(/* @__PURE__ */ g({
5
+ inheritAttrs: !1,
6
+ __name: "BVIconButton",
7
+ props: {
8
+ text: {},
9
+ href: {},
10
+ target: {},
11
+ rel: {},
12
+ size: { default: "medium" },
13
+ theme: { default: "brand" },
14
+ tag: {},
15
+ icon: {},
16
+ label: {}
17
+ },
18
+ setup(e) {
19
+ let t = e, n = u(() => !t.text);
20
+ return (t, r) => (x(), p("span", { class: v(["bv-icon-button", [e.size, {
21
+ "icon-only": n.value,
22
+ "has-icon": !!e.icon && !n.value
23
+ }]]) }, [h(s, _(t.$attrs, {
24
+ class: ["bv-icon-button-target", {
25
+ "icon-only": n.value,
26
+ "has-icon": !!e.icon && !n.value
27
+ }],
28
+ text: e.text ?? "",
29
+ href: e.href,
30
+ target: e.target,
31
+ rel: e.rel,
32
+ size: e.size,
33
+ theme: e.theme,
34
+ tag: e.tag,
35
+ "aria-label": n.value ? e.label : void 0
36
+ }), null, 16, [
37
+ "class",
38
+ "text",
39
+ "href",
40
+ "target",
41
+ "rel",
42
+ "size",
43
+ "theme",
44
+ "tag",
45
+ "aria-label"
46
+ ]), e.icon ? (x(), p("span", {
47
+ key: 0,
48
+ class: "bv-icon-button-icon",
49
+ innerHTML: e.icon
50
+ }, null, 8, E)) : f("", !0)], 2));
51
+ }
52
+ }), [["__scopeId", "data-v-6c0ea7e4"]]), O = /* @__PURE__ */ g({
53
+ __name: "BVPlatformButton",
54
+ props: {
55
+ manifestUrl: { default: "platformButton.json" },
56
+ fallbackHref: {},
57
+ fallbackLabel: {},
58
+ size: {},
59
+ theme: {},
60
+ target: {},
61
+ rel: {},
62
+ icon: {},
63
+ base: { default: "" }
64
+ },
65
+ setup(t) {
66
+ let r = t, o = S(null), { manifest: s } = i(() => a(r.base, r.manifestUrl));
67
+ b(() => {
68
+ o.value = n(typeof navigator > "u" ? void 0 : navigator);
69
+ });
70
+ let c = u(() => e(o.value, s.value, {
71
+ fallbackHref: r.fallbackHref,
72
+ fallbackLabel: r.fallbackLabel
73
+ }));
74
+ return (e, n) => c.value ? (x(), d(D, {
75
+ key: 0,
76
+ tag: "a",
77
+ text: c.value.label,
78
+ href: c.value.href,
79
+ target: t.target,
80
+ rel: t.rel,
81
+ size: t.size,
82
+ theme: t.theme,
83
+ icon: t.icon
84
+ }, null, 8, [
85
+ "text",
86
+ "href",
87
+ "target",
88
+ "rel",
89
+ "size",
90
+ "theme",
91
+ "icon"
92
+ ])) : f("", !0);
93
+ }
94
+ }), k = [
95
+ "href",
96
+ "target",
97
+ "rel"
98
+ ], A = ["innerHTML"], j = "<svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" fill=\"currentColor\" aria-hidden=\"true\"><circle cx=\"5\" cy=\"12\" r=\"2\"/><circle cx=\"12\" cy=\"12\" r=\"2\"/><circle cx=\"19\" cy=\"12\" r=\"2\"/></svg>", M = /*#__PURE__*/ t(/* @__PURE__ */ g({
99
+ __name: "BVMoreButton",
100
+ props: {
101
+ items: {},
102
+ icon: {},
103
+ text: { default: "More..." },
104
+ label: { default: "More options" },
105
+ size: {},
106
+ theme: {}
107
+ },
108
+ setup(e) {
109
+ let t = e, n = u(() => t.icon ?? (t.text ? null : j)), i = S(null), a = S(null), o = S(null), { open: s, panelLeft: d, panelTop: g, setItemRef: _, toggleMenu: v, onTriggerKeydown: b, onMenuKeydown: E } = c({
110
+ itemCount: () => t.items.length,
111
+ rootEl: i,
112
+ iconButtonEl: a,
113
+ panelEl: o
114
+ });
115
+ function O(e) {
116
+ return e.target ?? (r(e.href) ? "_blank" : void 0);
117
+ }
118
+ function M(e) {
119
+ return e.rel ?? (r(e.href) ? "noreferrer" : void 0);
120
+ }
121
+ return (t, r) => (x(), p("span", {
122
+ ref_key: "rootEl",
123
+ ref: i,
124
+ class: "bv-more-button"
125
+ }, [h(D, {
126
+ ref_key: "iconButtonEl",
127
+ ref: a,
128
+ text: e.text,
129
+ icon: n.value ?? void 0,
130
+ size: e.size,
131
+ theme: e.theme,
132
+ label: e.text ? void 0 : e.label,
133
+ "aria-haspopup": "menu",
134
+ "aria-expanded": T(s),
135
+ onClick: T(v),
136
+ onKeydown: T(b)
137
+ }, null, 8, [
138
+ "text",
139
+ "icon",
140
+ "size",
141
+ "theme",
142
+ "label",
143
+ "aria-expanded",
144
+ "onClick",
145
+ "onKeydown"
146
+ ]), T(s) ? (x(), p("div", {
147
+ key: 0,
148
+ ref_key: "panelEl",
149
+ ref: o,
150
+ class: "bv-more-button-panel",
151
+ role: "menu",
152
+ style: y({
153
+ left: `${T(d)}px`,
154
+ top: `${T(g)}px`
155
+ }),
156
+ onKeydown: r[0] ||= (...e) => T(E) && T(E)(...e)
157
+ }, [(x(!0), p(l, null, C(e.items, (e, t) => (x(), p("a", {
158
+ key: e.href,
159
+ ref_for: !0,
160
+ ref: (e) => T(_)(e, t),
161
+ role: "menuitem",
162
+ class: "bv-more-button-item",
163
+ href: e.href,
164
+ target: O(e),
165
+ rel: M(e)
166
+ }, [e.icon ? (x(), p("span", {
167
+ key: 0,
168
+ class: "bv-more-button-item-icon",
169
+ innerHTML: e.icon
170
+ }, null, 8, A)) : f("", !0), m(" " + w(e.label), 1)], 8, k))), 128))], 36)) : f("", !0)], 512));
171
+ }
172
+ }), [["__scopeId", "data-v-f229a206"]]);
173
+ //#endregion
174
+ export { s as BVButton, D as BVIconButton, M as BVMoreButton, O as BVPlatformButton, o as defaultLabels, n as detectPlatform, e as resolveDownload, a as resolveManifestUrl };
@@ -0,0 +1,10 @@
1
+ export { default as BVButton } from './BVButton.vue';
2
+ export type { BVButtonProps } from './BVButton.types';
3
+ export { default as BVIconButton } from './BVIconButton.vue';
4
+ export type { BVIconButtonProps } from './BVIconButton.types';
5
+ export { default as BVPlatformButton } from './BVPlatformButton.vue';
6
+ export { detectPlatform, resolveDownload, resolveManifestUrl, defaultLabels } from './platform';
7
+ export type { BVPlatformManifest, BVPlatformEntry, BVPlatformId } from './platform';
8
+ export type { BVPlatformButtonProps } from './BVPlatformButton.types';
9
+ export { default as BVMoreButton } from './BVMoreButton.vue';
10
+ export type { BVMoreButtonItem, BVMoreButtonProps } from './BVMoreButton.types';
@@ -0,0 +1,9 @@
1
+ export interface MenuPlacementInput {
2
+ triggerLeft: number;
3
+ triggerRight: number;
4
+ panelWidth: number;
5
+ viewportWidth: number;
6
+ }
7
+ export declare function computeMenuPanelLeft({ triggerLeft, triggerRight, panelWidth, viewportWidth, }: MenuPlacementInput): number;
8
+ export type MenuStepKey = 'ArrowDown' | 'ArrowUp' | 'Home' | 'End';
9
+ export declare function stepMenuIndex(key: MenuStepKey, currentIndex: number, itemCount: number): number;