Add prettier. Format.

This commit is contained in:
2026-07-22 02:12:05 +00:00
parent d28b09dc21
commit 18baa96848
45 changed files with 4520 additions and 2613 deletions

View File

@@ -3,11 +3,20 @@
"version": "0.1.0",
"type": "module",
"license": "MIT",
"files": ["dist"],
"sideEffects": ["./dist/style.css"],
"scripts": { "build": "vite build --config vite.config.ts && vue-tsc -p tsconfig.json --emitDeclarationOnly" },
"files": [
"dist"
],
"sideEffects": [
"./dist/style.css"
],
"scripts": {
"build": "vite build --config vite.config.ts && vue-tsc -p tsconfig.json --emitDeclarationOnly"
},
"exports": {
".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" },
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./style.css": "./dist/style.css"
},
"peerDependencies": {

View File

@@ -1,71 +1,103 @@
import { defineComponent, h, type PropType } from 'vue'
import type { RouteLocationNormalizedLoaded, RouteLocationRaw } from 'vue-router'
import { useNativeRouter } from '@native-vue-router/core'
import './style.css'
import { defineComponent, h, type PropType } from "vue";
import type {
RouteLocationNormalizedLoaded,
RouteLocationRaw,
} from "vue-router";
import { useNativeRouter } from "@native-vue-router/core";
import "./style.css";
export type NativePlatform = 'ios' | 'android' | 'desktop'
export type NativePlatform = "ios" | "android" | "desktop";
export function detectNativePlatform(): NativePlatform {
if (typeof navigator === 'undefined') return 'desktop'
if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent) && ('ontouchend' in document)) return 'ios'
if (/Android/.test(navigator.userAgent)) return 'android'
return 'desktop'
if (typeof navigator === "undefined") return "desktop";
if (
/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent) &&
"ontouchend" in document
)
return "ios";
if (/Android/.test(navigator.userAgent)) return "android";
return "desktop";
}
export const NativeBackButton = defineComponent({
name: 'NativeBackButton',
props: { label: { type: String, default: 'Back' } },
name: "NativeBackButton",
props: { label: { type: String, default: "Back" } },
setup(props) {
const native = useNativeRouter()
return () => h('button', {
type: 'button',
class: 'nvr-native-back',
'aria-label': props.label,
onClick: () => void native.pop(),
}, [h('span', { 'aria-hidden': 'true' }, ''), h('span', props.label)])
const native = useNativeRouter();
return () =>
h(
"button",
{
type: "button",
class: "nvr-native-back",
"aria-label": props.label,
onClick: () => void native.pop(),
},
[h("span", { "aria-hidden": "true" }, ""), h("span", props.label)],
);
},
})
});
export interface NativeTabItem {
label: string
to: RouteLocationRaw
icon?: string
activeWhen?: (current: RouteLocationNormalizedLoaded) => boolean
label: string;
to: RouteLocationRaw;
icon?: string;
activeWhen?: (current: RouteLocationNormalizedLoaded) => boolean;
}
export const NativeTabBar = defineComponent({
name: 'NativeTabBar',
name: "NativeTabBar",
props: {
items: { type: Array as PropType<NativeTabItem[]>, required: true },
},
setup(props) {
const native = useNativeRouter()
return () => h('nav', { class: 'nvr-native-tabs', 'aria-label': 'Primary navigation' },
props.items.map((item) => {
const current = native.router.currentRoute.value
const exact = current.path === native.router.resolve(item.to).path
const active = exact || Boolean(item.activeWhen?.(current))
const href = native.router.resolve(item.to).href
return h('a', {
href,
class: ['nvr-native-tab', active && 'nvr-native-tab--active'],
'aria-current': active ? 'page' : undefined,
onClick: (event: MouseEvent) => {
if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return
event.preventDefault()
if (exact) return
void native.sibling(item.to, { replace: true })
},
}, [
h('span', { class: 'nvr-native-tab__icon', 'aria-hidden': 'true' }, item.icon ?? '•'),
h('span', item.label),
])
}))
const native = useNativeRouter();
return () =>
h(
"nav",
{ class: "nvr-native-tabs", "aria-label": "Primary navigation" },
props.items.map((item) => {
const current = native.router.currentRoute.value;
const exact = current.path === native.router.resolve(item.to).path;
const active = exact || Boolean(item.activeWhen?.(current));
const href = native.router.resolve(item.to).href;
return h(
"a",
{
href,
class: ["nvr-native-tab", active && "nvr-native-tab--active"],
"aria-current": active ? "page" : undefined,
onClick: (event: MouseEvent) => {
if (
event.defaultPrevented ||
event.button !== 0 ||
event.metaKey ||
event.ctrlKey ||
event.shiftKey ||
event.altKey
)
return;
event.preventDefault();
if (exact) return;
void native.sibling(item.to, { replace: true });
},
},
[
h(
"span",
{ class: "nvr-native-tab__icon", "aria-hidden": "true" },
item.icon ?? "•",
),
h("span", item.label),
],
);
}),
);
},
})
});
export const nativeMotionTokens = {
ios: { edgeWidth: 28, commitThreshold: 0.36 },
android: { edgeWidth: 24, commitThreshold: 0.32 },
desktop: { edgeWidth: 18, commitThreshold: 0.4 },
} as const
} as const;

View File

@@ -30,9 +30,14 @@
display: grid;
grid-auto-flow: column;
grid-auto-columns: 1fr;
padding: 8px max(12px, var(--nvr-safe-right)) calc(8px + var(--nvr-safe-bottom)) max(12px, var(--nvr-safe-left));
padding: 8px max(12px, var(--nvr-safe-right))
calc(8px + var(--nvr-safe-bottom)) max(12px, var(--nvr-safe-left));
border-top: 1px solid color-mix(in srgb, currentColor 12%, transparent);
background: color-mix(in srgb, var(--nvr-view-background, #fff) 88%, transparent);
background: color-mix(
in srgb,
var(--nvr-view-background, #fff) 88%,
transparent
);
backdrop-filter: blur(24px) saturate(1.6);
}
@@ -48,9 +53,16 @@
font-weight: 600;
}
.nvr-native-tab--active { color: var(--nvr-accent); }
.nvr-native-tab__icon { font-size: 19px; line-height: 1.2; }
.nvr-native-tab--active {
color: var(--nvr-accent);
}
.nvr-native-tab__icon {
font-size: 19px;
line-height: 1.2;
}
@media (pointer: fine) and (min-width: 900px) {
.nvr-native-tabs { border-radius: 18px 18px 0 0; }
.nvr-native-tabs {
border-radius: 18px 18px 0 0;
}
}

View File

@@ -1,10 +1,18 @@
import { defineConfig } from 'vite'
import { resolve } from 'node:path'
import { defineConfig } from "vite";
import { resolve } from "node:path";
export default defineConfig({
build: {
outDir: 'dist', emptyOutDir: true,
lib: { entry: resolve(__dirname, 'src/index.ts'), formats: ['es'], fileName: 'index', cssFileName: 'style' },
rollupOptions: { external: ['vue', 'vue-router', '@native-vue-router/core'] },
outDir: "dist",
emptyOutDir: true,
lib: {
entry: resolve(__dirname, "src/index.ts"),
formats: ["es"],
fileName: "index",
cssFileName: "style",
},
rollupOptions: {
external: ["vue", "vue-router", "@native-vue-router/core"],
},
},
})
});