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.
- package/LICENSE.md +21 -0
- package/README.md +287 -0
- package/dist/BVButton.test.d.ts +1 -0
- package/dist/BVButton.types.d.ts +9 -0
- package/dist/BVButton.vue.d.ts +15 -0
- package/dist/BVIconButton.test.d.ts +1 -0
- package/dist/BVIconButton.types.d.ts +11 -0
- package/dist/BVIconButton.vue.d.ts +17 -0
- package/dist/BVMoreButton.test.d.ts +1 -0
- package/dist/BVMoreButton.types.d.ts +15 -0
- package/dist/BVMoreButton.vue.d.ts +20 -0
- package/dist/BVPlatformButton.test.d.ts +1 -0
- package/dist/BVPlatformButton.types.d.ts +10 -0
- package/dist/BVPlatformButton.vue.d.ts +17 -0
- package/dist/bojuvue.css +2 -0
- package/dist/bojuvue.js +174 -0
- package/dist/index.d.ts +10 -0
- package/dist/moreButtonMenu.d.ts +9 -0
- package/dist/moreButtonMenu.test.d.ts +1 -0
- package/dist/platform.d.ts +22 -0
- package/dist/platform.test.d.ts +1 -0
- package/dist/url.d.ts +1 -0
- package/dist/useManifestFetch.d.ts +53 -0
- package/dist/useMoreButtonMenu-BdAgqGZv.js +194 -0
- package/dist/useMoreButtonMenu.d.ts +16 -0
- package/dist/vitepress/BVButton.test.d.ts +1 -0
- package/dist/vitepress/BVButton.vue.d.ts +12 -0
- package/dist/vitepress/BVIconButton.test.d.ts +1 -0
- package/dist/vitepress/BVIconButton.vue.d.ts +17 -0
- package/dist/vitepress/BVMoreButton.test.d.ts +1 -0
- package/dist/vitepress/BVMoreButton.vue.d.ts +20 -0
- package/dist/vitepress/BVPlatformButton.test.d.ts +1 -0
- package/dist/vitepress/BVPlatformButton.vue.d.ts +15 -0
- package/dist/vitepress.d.ts +10 -0
- package/dist/vitepress.js +223 -0
- 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 보주뷰 [](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,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,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,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;
|
package/dist/bojuvue.css
ADDED
|
@@ -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*/
|
package/dist/bojuvue.js
ADDED
|
@@ -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 };
|
package/dist/index.d.ts
ADDED
|
@@ -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;
|