Compare commits

..

1 Commits

Author SHA1 Message Date
Benjamin Canac
fd95a3f646 fix(module): handle tailwindMerge config from app.config 2023-12-15 14:55:28 +01:00
345 changed files with 6038 additions and 8464 deletions

View File

@@ -4,7 +4,7 @@
### 🔗 Linked issue
<!-- If it resolves an open issue, please link the issue here. For example "Resolves #123" -->
<!-- Please ensure there is an open issue and mention its number as #123 -->
### ❓ Type of change
@@ -21,6 +21,7 @@
<!-- Describe your changes in detail -->
<!-- Why is this change required? What problem does it solve? -->
<!-- If it resolves an open issue, please link to the issue here. For example "Resolves #1337" -->
### 📝 Checklist

View File

@@ -45,7 +45,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
@@ -53,7 +53,7 @@ jobs:
restore-keys: |
${{ runner.os }}-pnpm-store-
- uses: dorny/paths-filter@v3
- uses: dorny/paths-filter@v2
id: changes
with:
filters: |

View File

@@ -38,7 +38,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}

1
.npmrc
View File

@@ -1,3 +1,2 @@
shamefully-hoist=true
auto-install-peers=true
ignore-workspace-root-check=true

View File

@@ -1,7 +1,6 @@
{
"git": {
"commitMessage": "chore(release): ${version}",
"tagName": "v${version}"
"commitMessage": "chore(release): ${version}"
},
"npm": {
"publish": false
@@ -12,7 +11,7 @@
"web": true
},
"hooks": {
"before:init": ["pnpm lint", "pnpm typecheck"]
"before:init": ["pnpm lint"]
},
"plugins": {
"@release-it/conventional-changelog": {

View File

@@ -1,157 +1,5 @@
# Changelog
## [2.14.1](https://github.com/nuxt/ui/compare/v2.14.0...v2.14.1) (2024-02-23)
### Bug Fixes
* **module:** revert tailwind config from [#1272](https://github.com/nuxt/ui/issues/1272) ([#1404](https://github.com/nuxt/ui/issues/1404)) ([ba15add](https://github.com/nuxt/ui/commit/ba15add4db5d2f84e987819628cbbf88edcbad57))
## [2.14.0](https://github.com/nuxt/ui/compare/v2.13.0...v2.14.0) (2024-02-22)
### Features
* **Carousel:** expose methods to allow autoplay ([41ecd2a](https://github.com/nuxt/ui/commit/41ecd2a3d553886db3e32d9f48a477268d93f3c6)), closes [#1300](https://github.com/nuxt/ui/issues/1300)
* **Divider:** handle `size` prop ([#1307](https://github.com/nuxt/ui/issues/1307)) ([cbeede6](https://github.com/nuxt/ui/commit/cbeede66bb3bd7778e03c19ebbf55bf7bd753cb8))
* **Form:** use nuxt `useId` to bind input labels ([#1211](https://github.com/nuxt/ui/issues/1211)) ([27c71fa](https://github.com/nuxt/ui/commit/27c71fa40ecb9f8524fee7f3d17a384bc8812d25))
* **Input:** handle type `file` ([946a39c](https://github.com/nuxt/ui/commit/946a39c73990dc352cf7b9a77bfaec339cdcab34)), closes [#563](https://github.com/nuxt/ui/issues/563)
* **Modal:** open programmatically ([#1319](https://github.com/nuxt/ui/issues/1319)) ([6f29c62](https://github.com/nuxt/ui/commit/6f29c620ab758e27be63f8af53674828b59fb6ed))
* **Table:** display progress bar when `loading` ([#1362](https://github.com/nuxt/ui/issues/1362)) ([3fe3521](https://github.com/nuxt/ui/commit/3fe35217cbc0cef7f41550c175e4e7ea2cc939a8))
* **Tabs:** add `unmount` prop as `false` by default ([843a978](https://github.com/nuxt/ui/commit/843a9786445f6170c1380e3b404151da52b5a154)), closes [#663](https://github.com/nuxt/ui/issues/663)
* **Textarea:** add `maxrows` prop to restrict autoresize ([#1302](https://github.com/nuxt/ui/issues/1302)) ([f643e7b](https://github.com/nuxt/ui/commit/f643e7b316639a79cf03da25250ab0fa85f466d5))
### Bug Fixes
* **Accordion:** style disclosure `div` after [#1199](https://github.com/nuxt/ui/issues/1199) ([882247e](https://github.com/nuxt/ui/commit/882247e5f40bf41fdfdffea501de5c898a7fb0b2))
* **Alert:** remove `required` title to prevent warning when using slot ([e545b6f](https://github.com/nuxt/ui/commit/e545b6f0a128475166dcea3c1028798b106805f3))
* **Card:** prevent `body` padding without default slot ([f682905](https://github.com/nuxt/ui/commit/f682905b26a22546634e9adc4b838a7741dbd7c9))
* **components:** hydration attribute mismatch with vue `3.4` ([#1199](https://github.com/nuxt/ui/issues/1199)) ([10db144](https://github.com/nuxt/ui/commit/10db14475f7a527180be3fcf33cc5d3af52452c9))
* **Form:** improve `validate` path type ([#1370](https://github.com/nuxt/ui/issues/1370)) ([5266591](https://github.com/nuxt/ui/commit/5266591c886422d5265e46e08e1276913d12bed1))
* **Form:** return false when silent validation fails ([#1371](https://github.com/nuxt/ui/issues/1371)) ([d4b6147](https://github.com/nuxt/ui/commit/d4b6147fcceb7ff9cebe1586bb3094b10f50acb5))
* **Link:** check `disabled` prop before navigating ([#1321](https://github.com/nuxt/ui/issues/1321)) ([ac42ec1](https://github.com/nuxt/ui/commit/ac42ec106ff259e1d44515e5fb3b5236559ac713))
* **Meter:** missing import of `Icon` component ([f8b296f](https://github.com/nuxt/ui/commit/f8b296fc60b93c4656fd397f8eb6b06b4a1dcd93)), closes [#1328](https://github.com/nuxt/ui/issues/1328)
* **module:** prevent tailwind warn with `bun` ([bb40c31](https://github.com/nuxt/ui/commit/bb40c3103174a039f65b31c65fcc5d40cb29ce6b)), closes [#809](https://github.com/nuxt/ui/issues/809)
* **module:** put back `all` option in icons plugin ([412cd75](https://github.com/nuxt/ui/commit/412cd75eddb6140d7d9b3358b04df1e61f22b481)), closes [#1237](https://github.com/nuxt/ui/issues/1237)
* **Notification:** remove `required` title to prevent warning when using slot ([aa2b1ca](https://github.com/nuxt/ui/commit/aa2b1cae8881dece9a629dc95a8f9df88f9bbd27))
* **Progress:** prevent `NaN` percent display when indeterminate ([a55a08a](https://github.com/nuxt/ui/commit/a55a08a91eca6f4c7ff3ad40ee566b6445d2dfd0))
* **RadioGroup:** pass `help` prop to radio children ([5a5b284](https://github.com/nuxt/ui/commit/5a5b284e967ca9cdb6c7df9809ed4f4569a65cfa)), closes [#1313](https://github.com/nuxt/ui/issues/1313)
* **SelectMenu:** revert component `is` after [#1199](https://github.com/nuxt/ui/issues/1199) ([d0f4530](https://github.com/nuxt/ui/commit/d0f4530e8572a08d544041dec1f24a51bbc3b1e8))
* **utils:** prevent merge of `popper` key ([9f35297](https://github.com/nuxt/ui/commit/9f352976ced5845a5fad00a6630d0166941a8a13)), closes [#1393](https://github.com/nuxt/ui/issues/1393)
### Reverts
* Revert "docs: add missing `overflow-hidden` on components" ([b893607](https://github.com/nuxt/ui/commit/b8936070f9e1f866a21d39f6c45140f86efebec4))
## [2.13.0](https://github.com/nuxt/ui/compare/v2.12.3...v2.13.0) (2024-01-30)
### ⚠ BREAKING CHANGES
* **VerticalNavigation:** use `Badge` component for consistency
### Features
* **Carousel:** new component ([#927](https://github.com/nuxt/ui/issues/927)) ([f37b043](https://github.com/nuxt/ui/commit/f37b0431382867c24a0eff511ae151115cdfa2a2))
* **Dropdown:** default delay from config ([c4a1c04](https://github.com/nuxt/ui/commit/c4a1c04174d612e8c4cdd430067a3bdf3d69f4bf))
* **Form:** handle multiple paths in `validate` ([#1273](https://github.com/nuxt/ui/issues/1273)) ([20ac4b3](https://github.com/nuxt/ui/commit/20ac4b3332267491067f3a5a393ca97e3ec6bab5))
* **HorizontalNavigation:** new component ([#1279](https://github.com/nuxt/ui/issues/1279)) ([b8007ba](https://github.com/nuxt/ui/commit/b8007bab5efde70a375d6e3b9be91a0b698485b1))
* **InputMenu:** handle `nullable` prop when clearing input ([5e49fb8](https://github.com/nuxt/ui/commit/5e49fb8736e01889b8f7a60cf0edc420e49fe52c))
* **Modal/Slideover:** emit `close-prevented` event ([#1207](https://github.com/nuxt/ui/issues/1207)) ([6faf15b](https://github.com/nuxt/ui/commit/6faf15bc7460d7473ec47de48e407d45cf7d2e26))
* **module:** add option to disable global css styles ([#1266](https://github.com/nuxt/ui/issues/1266)) ([f96eb5e](https://github.com/nuxt/ui/commit/f96eb5e8b794af75303a98fa38e5285bcf928614))
* **Popover:** default delay from config ([7f5711b](https://github.com/nuxt/ui/commit/7f5711bc76cc509079934fd15ebbccb82bced064))
* **Tooltip:** default delay from config ([3400b56](https://github.com/nuxt/ui/commit/3400b56d82c1713e67838ba246bba687f3056fe6))
* **VerticalNavigation:** use `Badge` component for consistency ([3e81eee](https://github.com/nuxt/ui/commit/3e81eee6e6dc066dda9e2270e183a76bc8695996))
### Bug Fixes
* **Breadrumb:** handle truncate ([5d3a962](https://github.com/nuxt/ui/commit/5d3a962782781e4204d24a2f240974612912f7ee))
* **Link:** propagate `active` prop to slot as `isActive` ([b76e761](https://github.com/nuxt/ui/commit/b76e761bbb98fe7bbd19fba16220e26fd96e9731))
* **Select:** consistent placeholder with input and textarea ([2cb41db](https://github.com/nuxt/ui/commit/2cb41db111da79f4f3f8ccd825071820050ba885)), closes [#1276](https://github.com/nuxt/ui/issues/1276)
* **Slideover:** handle translate in RTL mode ([#1259](https://github.com/nuxt/ui/issues/1259)) ([ea58c88](https://github.com/nuxt/ui/commit/ea58c88baab3a0684e5b0140895ee630087ea044))
## [2.12.3](https://github.com/nuxt/ui/compare/v2.12.2...v2.12.3) (2024-01-18)
### Bug Fixes
* **link:** import type from `[#vue](https://github.com/nuxt/ui/issues/vue)-router` ([79ec3fd](https://github.com/nuxt/ui/commit/79ec3fd031e28d15854e2f0d4fb978df337e43d5)), closes [#1253](https://github.com/nuxt/ui/issues/1253)
## [2.12.2](https://github.com/nuxt/ui/compare/v2.12.1...v2.12.2) (2024-01-18)
### Bug Fixes
* **link:** improve nuxt link `rel` type ([05e90aa](https://github.com/nuxt/ui/commit/05e90aa1d13ab1772189d33278f482405ff88975))
## [2.12.1](https://github.com/nuxt/ui/compare/v2.12.0...v2.12.1) (2024-01-18)
### Bug Fixes
* **Button:** inherit nuxt link props without breaking `nuxt-component-meta` ([d3e19dc](https://github.com/nuxt/ui/commit/d3e19dc65a530201c3adc7738e95e5a09b0a9274)), closes [#578](https://github.com/nuxt/ui/issues/578)
* **Button:** pass-through nuxt link props to `ULink` ([a44bfc8](https://github.com/nuxt/ui/commit/a44bfc85114bed15ed25bb8c79d7ed52adc8d43c))
* **InputMenu:** take `option-attribute` into account to display label ([1a93791](https://github.com/nuxt/ui/commit/1a937919a26546cfd7edb3f6a11ef790d401999d))
* **Link:** prevent `type` bind on `<a>` ([b0df864](https://github.com/nuxt/ui/commit/b0df86437902696b594e5e7042601506a8bf4436))
* **SelectMenu:** take `option-attribute` into account to display label ([b9fe74b](https://github.com/nuxt/ui/commit/b9fe74bca5f48555e76c16237c2acc868f69e243)), closes [#1151](https://github.com/nuxt/ui/issues/1151)
* **Tooltip:** typo in kbd component ([4405d32](https://github.com/nuxt/ui/commit/4405d3239f7e19d399659347f079555318b3231b))
## [2.12.0](https://github.com/nuxt/ui/compare/v2.11.1...v2.12.0) (2024-01-09)
### ⚠ BREAKING CHANGES
* **Card:** remove `overflow-hidden` on wrapper
### Features
* **Breadcrumb:** handle `labelClass` and merge `iconClass` ([f623ec1](https://github.com/nuxt/ui/commit/f623ec1130edf448988784b36c15a850470685c4))
* **Dropdown:** handle `labelClass` and merge `iconClass` ([1c9835d](https://github.com/nuxt/ui/commit/1c9835d7f149231cf2e3e053e5ea08eceeaaa61d)), closes [#716](https://github.com/nuxt/ui/issues/716)
* **Dropdown:** handle manual mode ([3844714](https://github.com/nuxt/ui/commit/38447146445618a1310a6315c608f4cd21069e17)), closes [#1143](https://github.com/nuxt/ui/issues/1143)
* **Form:** expose submit function ([#1186](https://github.com/nuxt/ui/issues/1186)) ([4a25a12](https://github.com/nuxt/ui/commit/4a25a12390f8ecae83c1081c89eba99a8fda14f8))
* **InputMenu:** new component ([#1095](https://github.com/nuxt/ui/issues/1095)) ([6d8d82a](https://github.com/nuxt/ui/commit/6d8d82a265692aaee556e40b09e4b3048ae044da))
* **Pagination:** add `disabled` prop ([0976833](https://github.com/nuxt/ui/commit/0976833753cd2140649bc324f53a263d4e09ecff)), closes [#1189](https://github.com/nuxt/ui/issues/1189)
* **Popover:** open and close events ([#1038](https://github.com/nuxt/ui/issues/1038)) ([f32f578](https://github.com/nuxt/ui/commit/f32f578125c12b35e59db2f7981c8b1b5a146397))
* **SelectMenu:** add `empty` slot when no options ([5d1919a](https://github.com/nuxt/ui/commit/5d1919a5381b316637d50405d287428f67f2b9cc)), closes [#1089](https://github.com/nuxt/ui/issues/1089)
* **SelectMenu:** allow control of search query ([f735db0](https://github.com/nuxt/ui/commit/f735db04d62fca678ca30ecd565b32e70bcda3e0)), closes [#1174](https://github.com/nuxt/ui/issues/1174)
* **SelectMenu:** allow creating option despite search ([#1080](https://github.com/nuxt/ui/issues/1080)) ([0fdc8f7](https://github.com/nuxt/ui/commit/0fdc8f70b6a656114d30b07d682e4edcd61a23fb))
* **Table:** add `sort-mode` prop ([56e0c9a](https://github.com/nuxt/ui/commit/56e0c9a9a05e1e8491e2d460b8d51084bd2c1305)), closes [#1149](https://github.com/nuxt/ui/issues/1149)
* **Table:** add custom sort function to columns ([#1075](https://github.com/nuxt/ui/issues/1075)) ([4f3af6c](https://github.com/nuxt/ui/commit/4f3af6cfdb5213d1be3d2680fcf3a95f7b3bc0b3))
* **VerticalNavigation:** ability to add dividers ([#963](https://github.com/nuxt/ui/issues/963)) ([ffd20b3](https://github.com/nuxt/ui/commit/ffd20b3991a35ae7fa0e249fa009e330fd963705))
* **VerticalNavigation:** handle `labelClass` and merge `iconClass` ([a79f7c0](https://github.com/nuxt/ui/commit/a79f7c0a34c0414fe4feb95691e1f044b07ef087))
* **VerticalNavigation:** improve accessibility ([#948](https://github.com/nuxt/ui/issues/948)) ([29e64ca](https://github.com/nuxt/ui/commit/29e64ca963eeed1e82640957860f43391d8683ed))
### Bug Fixes
* **Alert:** always pass a function to actions click events ([5d78111](https://github.com/nuxt/ui/commit/5d781112f1eb464658c83047bf80c2ea7c9a2b05)), closes [#1197](https://github.com/nuxt/ui/issues/1197)
* **Card:** remove `overflow-hidden` on wrapper ([4124406](https://github.com/nuxt/ui/commit/412440603206151d63b04ffe6bed1bbc5b0e6615)), closes [#806](https://github.com/nuxt/ui/issues/806) [#1034](https://github.com/nuxt/ui/issues/1034)
* **config:** prevent class merge of `avatar` size ([b22bd70](https://github.com/nuxt/ui/commit/b22bd70d54e68c3217ba42690210084749fee656))
* **Dropdown:** improve placement with `hover` mode ([c6aa421](https://github.com/nuxt/ui/commit/c6aa4215d7f9003adeefa7cdff76c7a88715f20c)), closes [#1179](https://github.com/nuxt/ui/issues/1179)
* **Dropdown:** merge item `class` ([7151b7b](https://github.com/nuxt/ui/commit/7151b7b97d42f389506521044ebaffa8a299e7fb)), closes [#1157](https://github.com/nuxt/ui/issues/1157)
* **Form:** invalid errors when using `clear` by path ([#1165](https://github.com/nuxt/ui/issues/1165)) ([97a3975](https://github.com/nuxt/ui/commit/97a39751977bf1e942e2bafd5839141383b7af2f))
* **Form:** memory leak ([#1185](https://github.com/nuxt/ui/issues/1185)) ([ea2a24b](https://github.com/nuxt/ui/commit/ea2a24b5fe6ddc87e6eb951a662ce8b84b9d987f))
* **forms:** dont disable inputs and selects on `loading` ([3258167](https://github.com/nuxt/ui/commit/3258167a1431b664cd1dcc925a4b3fe06a996831)), closes [#1117](https://github.com/nuxt/ui/issues/1117)
* **Link:** handle `active` override when value is false ([83631cc](https://github.com/nuxt/ui/commit/83631ccbca1364f012b0c2899f97e2166dd1d360))
* **Popover:** allow manual mode without blocking normal behaviour ([3334e2a](https://github.com/nuxt/ui/commit/3334e2af3de2844de08ee530e62f2e4e2fd7ed24))
* **Popover:** improve placement with `hover` mode ([bc00f9c](https://github.com/nuxt/ui/commit/bc00f9c4b25dd4b99cb6e53014624f41ee929654)), closes [#781](https://github.com/nuxt/ui/issues/781)
* **RadioGroup:** pass `option.disabled` to children ([0c8ab9d](https://github.com/nuxt/ui/commit/0c8ab9d98e494c49cceac111edc0606ee4d63638)), closes [#1109](https://github.com/nuxt/ui/issues/1109)
* **SelectMenu:** input border focus after `tailwindcss` 3.4 ([e8f573b](https://github.com/nuxt/ui/commit/e8f573b6bb32a22873d9f93b40883ca12b481d7e))
* **Table:** display nothing instead of error when key is missing ([00d0fd5](https://github.com/nuxt/ui/commit/00d0fd59192cc171abb3d2ddaee46b2b9fa9422f)), closes [#1173](https://github.com/nuxt/ui/issues/1173)
* **Table:** respect sort prop updates from parent component ([#1208](https://github.com/nuxt/ui/issues/1208)) ([c6841d0](https://github.com/nuxt/ui/commit/c6841d06a48ffef95d238f94a4822a1e48b85422))
* **Toggle:** add missing `change` event ([4c84839](https://github.com/nuxt/ui/commit/4c84839a0183756b9f8df8674aace8cd40e44dcd)), closes [#1113](https://github.com/nuxt/ui/issues/1113)
* update vue and fix type issues ([#1112](https://github.com/nuxt/ui/issues/1112)) ([5c99ae1](https://github.com/nuxt/ui/commit/5c99ae131d1a50a8db21f1d5794a06080c515831))
* **useShortcuts:** include `contenteditable="plaintext-only"` elements in `usingInput` ([#1159](https://github.com/nuxt/ui/issues/1159)) ([648eec3](https://github.com/nuxt/ui/commit/648eec31b99fcffb65c042e0a5587da941c8e90f))
* **useShortcuts:** invalid code after [#1159](https://github.com/nuxt/ui/issues/1159) ([56e1fed](https://github.com/nuxt/ui/commit/56e1fed373786fc158ca9da9f02a9ec4e273afce))
### Reverts
* Revert "docs: pull `nuxt/ui-pro` docs from `main` branch" ([d0ce8ee](https://github.com/nuxt/ui/commit/d0ce8ee1c4a3d7b2285885d76e02e03168011110))
## [2.11.1](https://github.com/nuxt/ui/compare/v2.11.0...v2.11.1) (2023-12-11)

View File

@@ -1,4 +1,4 @@
[![nuxt-ui.png](https://repository-images.githubusercontent.com/428329515/43fec891-9030-4601-8233-5d45ba5c6013)](https://ui.nuxt.com)
[![nuxt-ui-social-card](https://repository-images.githubusercontent.com/428329515/43fec891-9030-4601-8233-5d45ba5c6013)](https://ui.nuxt.com)
# Nuxt UI
@@ -7,9 +7,9 @@
[![License][license-src]][license-href]
[![Nuxt][nuxt-src]][nuxt-href]
Nuxt UI is a module that provides a set of Vue components and composables built with [Tailwind CSS](https://tailwindcss.com/) and [Headless UI](https://headlessui.dev/) to help you build beautiful and accessible user interfaces.
Nuxt UI provides everything related to UI when building Nuxt applications: components, icons, colors, dark mode and also keyboard shortcuts.
Its goal is to provide everything related to UI when building a Nuxt app. This includes components, icons, colors, dark mode but also keyboard shortcuts.
Is has been developed by [NuxtLabs](https://nuxtlabs.com/) for [Volta](https://volta.net), [Nuxt Studio](https://nuxt.studio/) and the Nuxt community.
## Features
@@ -27,14 +27,14 @@ Read more on [ui.nuxt.com](https://ui.nuxt.com)
## Installation
```bash
# npm
# Using npm
npm install @nuxt/ui
# yarn
# Using yarn
yarn add @nuxt/ui
# pnpm
# Using pnpm
pnpm add @nuxt/ui
# bun
bun add @nuxt/ui
```
Then, register the module in your `nuxt.config.ts`:

View File

@@ -1,10 +1,6 @@
<!-- eslint-disable vue/no-v-html -->
<template>
<div>
<NuxtLoadingIndicator />
<Banner />
<Header v-if="!$route.path.startsWith('/examples')" :links="links" />
<NuxtLayout>
@@ -14,7 +10,7 @@
<Footer v-if="!$route.path.startsWith('/examples')" />
<ClientOnly>
<LazyUContentSearch ref="searchRef" :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" />
<LazyUDocsSearch ref="searchRef" :files="files" :navigation="navigation" :groups="groups" :links="links" />
</ClientOnly>
<UNotifications>
@@ -22,7 +18,6 @@
<span v-html="title" />
</template>
</UNotifications>
<UModals />
</div>
</template>
@@ -35,7 +30,7 @@ const searchRef = ref()
const route = useRoute()
const colorMode = useColorMode()
const { branch } = useContentSource()
const { branch, branches } = useContentSource()
const { data: nav } = await useAsyncData('navigation', () => fetchContentNavigation())
const { data: files } = useLazyFetch<ParsedContent[]>('/api/search.json', { default: () => [], server: false })
@@ -53,31 +48,54 @@ const navigation = computed(() => {
]
}
return nav.value?.filter(item => item._path !== '/dev') || []
return nav.value.filter(item => item._path !== '/dev')
})
const groups = computed(() => {
if (route.path === '/') {
return []
}
return [{ key: 'branch', label: 'Branch', commands: branches.value }]
})
const color = computed(() => colorMode.value === 'dark' ? '#18181b' : 'white')
const links = computed(() => {
return [{
label: 'Docs',
label: 'Documentation',
icon: 'i-heroicons-book-open',
to: branch.value?.name === 'dev' ? '/dev/getting-started' : '/getting-started',
active: branch.value?.name === 'dev' ? (route.path.startsWith('/dev/getting-started') || route.path.startsWith('/dev/components')) : (route.path.startsWith('/getting-started') || route.path.startsWith('/components'))
}, ...(navigation.value.find(item => item._path === '/pro') ? [{
to: `${branch.value?.name === 'dev' ? '/dev' : ''}/getting-started`
}, {
label: 'Playground',
icon: 'i-simple-icons-stackblitz',
to: '/playground'
}, {
label: 'Roadmap',
icon: 'i-heroicons-academic-cap',
to: '/roadmap'
}, !!navigation.value.find(item => item._path === '/pro') && {
label: 'Pro',
icon: 'i-heroicons-square-3-stack-3d',
to: '/pro',
active: route.path.startsWith('/pro/getting-started') || route.path.startsWith('/pro/components') || route.path.startsWith('/pro/prose')
children: [{
label: 'Features',
to: '/pro',
exact: true,
icon: 'i-heroicons-beaker',
description: 'Discover all the features of Nuxt UI Pro.'
}, {
label: 'Guide',
to: '/pro/guide',
icon: 'i-heroicons-book-open',
description: 'Learn how to use Nuxt UI Pro in your app.'
}, {
label: 'Components',
to: '/pro/components',
icon: 'i-heroicons-cube-transparent',
description: 'Discover all the components available in Nuxt UI Pro.'
}]
}, {
label: 'Pricing',
icon: 'i-heroicons-credit-card',
to: '/pro/pricing'
}, {
label: 'Templates',
icon: 'i-heroicons-computer-desktop',
to: '/pro/templates'
}] : []), {
label: 'Releases',
icon: 'i-heroicons-rocket-launch',
to: '/releases'

View File

@@ -1,76 +0,0 @@
<script setup lang="ts">
import { isAfter } from 'date-fns'
const id = 'nuxt-ui-banner-1'
const to = '/pro/pricing'
const date = new Date('2024-02-25T20:00:00Z')
const timeAgo = useTimeAgo(date)
const hideBanner = () => {
localStorage.setItem(id, 'true')
document.querySelector('html')?.classList.add('hide-banner')
}
if (process.server) {
useHead({
script: [{
key: 'prehydrate-template-banner',
innerHTML: `
if (localStorage.getItem('${id}') === 'true') {
document.querySelector('html').classList.add('hide-banner')
}`.replace(/\s+/g, ' '),
type: 'text/javascript'
}]
})
}
onMounted(() => {
if (isAfter(new Date(), date)) {
hideBanner()
return
}
const interval = setInterval(() => {
if (isAfter(new Date(), date)) {
hideBanner()
clearInterval(interval)
}
}, 1000)
})
</script>
<template>
<div class="relative bg-primary hover:bg-primary/90 transition-[background] backdrop-blur z-50 app-banner">
<UContainer class="py-2">
<NuxtLink v-if="to" :to="to" class="focus:outline-none" tabindex="-1">
<span class="absolute inset-0 " aria-hidden="true" />
</NuxtLink>
<div class="flex items-center justify-between gap-2">
<div class="lg:flex-1 hidden lg:flex items-center" />
<p class="text-sm font-medium text-white dark:text-gray-900">
<UIcon name="i-heroicons-gift" class="w-5 h-5 align-top flex-shrink-0 pointer-events-none mr-2" />
<span class="font-semibold">Nuxt UI Pro v1.0</span> is out with dashboard components! Discount ends <span class="font-semibold">{{ timeAgo }}</span>.
</p>
<div class="flex items-center justify-end lg:flex-1">
<button
class="p-1.5 rounded-md inline-flex hover:bg-primary/90"
@click.prevent="hideBanner"
>
<UIcon name="i-heroicons-x-mark-20-solid" class="w-5 h-5 text-white dark:text-gray-900" />
</button>
</div>
</div>
</UContainer>
</div>
</template>
<style scoped>
.hide-banner .app-banner {
display: none;
}
</style>

View File

@@ -1,34 +1,36 @@
<template>
<div class="mb-3 lg:mb-6">
<UDropdown
class="w-full"
:items="[branches]"
<label for="branch" class="block mb-1.5 font-semibold text-sm/6">Version</label>
<USelectMenu
id="branch"
:model-value="branch"
name="branch"
:options="branches"
color="gray"
mode="hover"
:ui="{ width: 'w-full' }"
:popper="{ strategy: 'absolute', placement: 'bottom' }"
:ui="{ icon: { trailing: { padding: { sm: 'pe-1.5' } } } }"
:ui-menu="{ option: { container: 'gap-1.5' } }"
@update:model-value="select"
>
<UButton color="gray" class="w-full">
<template #label>
<UIcon v-if="branch.icon" :name="branch.icon" class="w-4 h-4 flex-shrink-0 text-gray-600 dark:text-gray-300" />
<span class="text-gray-900 dark:text-white">{{ branch.label }}</span>
<span class="font-medium">{{ branch.label }}</span>
<span class="text-gray-400 dark:text-gray-500">{{ branch.suffix }}</span>
<UIcon name="i-heroicons-chevron-down-20-solid" class="w-5 h-5 text-gray-400 dark:text-gray-500 ml-auto -mr-1" />
</UButton>
<template #item="{ item }">
<UIcon v-if="item.icon" :name="item.icon" class="w-4 h-4 flex-shrink-0 text-gray-600 dark:text-gray-300" />
<span>{{ item.label }}</span>
<span class="truncate text-gray-400 dark:text-gray-500">{{ item.suffix }}</span>
<span class="truncate text-gray-400 dark:text-gray-500">{{ branch.suffix }}</span>
</template>
</UDropdown>
<template #option="{ option }">
<UIcon v-if="option.icon" :name="option.icon" class="w-4 h-4 flex-shrink-0 text-gray-600 dark:text-gray-300" />
<span class="font-medium">{{ option.label }}</span>
<span class="truncate text-gray-400 dark:text-gray-500">{{ option.suffix }}</span>
</template>
</USelectMenu>
</div>
</template>
<script setup lang="ts">
const { branches, branch } = useContentSource()
const { branches, branch, select } = useContentSource()
</script>

View File

@@ -5,19 +5,21 @@
</div>
</div>
<UFooter :links="links">
<UFooter>
<template #left>
<NuxtLink v-if="$route.path.startsWith('/pro')" to="https://ui.nuxt.com/pro/purchase" target="_blank" class="text-sm text-gray-500 dark:text-gray-400">
Purchase <span class="text-gray-900 dark:text-white">Nuxt UI Pro</span>
</NuxtLink>
<NuxtLink v-else to="https://github.com/nuxt/ui" target="_blank" class="text-sm text-gray-500 dark:text-gray-400">
Published under <span class="text-gray-900 dark:text-white">MIT License</span>
</NuxtLink>
<a v-if="$route.path.startsWith('/pro')" class="text-sm text-gray-500 dark:text-gray-400 hover:underline" href="https://ui.nuxt.com/pro/purchase" target="_blank">
Purchase Nuxt UI Pro
</a>
<span v-else class="text-sm text-gray-500 dark:text-gray-400">
Published under <NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-gray-900 dark:text-white">
MIT License
</NuxtLink>
</span>
</template>
<template #right>
<UButton aria-label="Nuxt Website" icon="i-simple-icons-nuxtdotjs" to="https://nuxt.com" target="_blank" v-bind="($ui.button.secondary as any)" />
<UButton aria-label="Nuxt UI on Discord" icon="i-simple-icons-discord" to="https://chat.nuxt.dev" target="_blank" v-bind="($ui.button.secondary as any)" />
<UButton aria-label="Nuxt UI on Discord" icon="i-simple-icons-discord" to="https://discord.com/invite/ps2h6QT" target="_blank" v-bind="($ui.button.secondary as any)" />
<UButton aria-label="Nuxt on X" icon="i-simple-icons-x" to="https://x.com/nuxt_js" target="_blank" v-bind="($ui.button.secondary as any)" />
<UButton aria-label="Nuxt UI on GitHub" icon="i-simple-icons-github" to="https://github.com/nuxt/ui" target="_blank" v-bind="($ui.button.secondary as any)" />
</template>
@@ -25,23 +27,5 @@
</template>
<script setup lang="ts">
const links = [{
icon: 'i-simple-icons-figma',
label: 'Figma Kit',
to: 'https://www.figma.com/community/file/1288455405058138934',
target: '_blank'
}, {
label: 'Playground',
icon: 'i-simple-icons-stackblitz',
to: 'https://stackblitz.com/edit/nuxt-ui',
target: '_blank'
}, {
label: 'Roadmap',
icon: 'i-heroicons-map',
to: '/roadmap'
}, {
label: 'Releases',
icon: 'i-heroicons-rocket-launch',
to: '/releases'
}]
// force typescript
</script>

View File

@@ -7,19 +7,16 @@
}"
>
<template #left>
<NuxtLink to="/" class="flex items-end gap-2 font-bold text-xl text-gray-900 dark:text-white" aria-label="Nuxt UI">
<NuxtLink to="/" class="flex items-end gap-1.5 font-bold text-xl text-gray-900 dark:text-white" aria-label="Nuxt UI">
<Logo class="w-auto h-6" />
<UBadge v-if="$route.path.startsWith('/pro')" label="Pro" variant="subtle" size="xs" class="-mb-[2px] rounded font-semibold" />
<UBadge v-if="$route.path.startsWith('/dev')" label="Edge" variant="subtle" size="xs" class="-mb-[2px] rounded font-semibold" />
</NuxtLink>
</template>
<template #right>
<ColorPicker />
<UTooltip text="Search" :shortcuts="[metaSymbol, 'K']" :popper="{ strategy: 'absolute' }">
<UContentSearchButton :label="null" />
<UTooltip text="Search" :shortcuts="[metaSymbol, 'K']">
<UDocsSearchButton :label="null" />
</UTooltip>
<UColorModeButton />
@@ -36,9 +33,9 @@
<template #panel>
<UAsideLinks :links="links" />
<UDivider type="dashed" class="my-4" />
<UDivider type="dashed" class="mt-4 mb-3" />
<BranchSelect />
<BranchSelect v-if="!route.path.startsWith('/pro')" />
<UNavigationTree :links="mapContentNavigation(navigation)" :multiple="false" default-open />
</template>
@@ -47,10 +44,10 @@
<script setup lang="ts">
import type { NavItem } from '@nuxt/content/dist/runtime/types'
import type { HeaderLink } from '#ui-pro/types'
import type { Link } from '#ui-pro/types'
defineProps<{
links: HeaderLink[]
links: Link[]
}>()
const route = useRoute()

View File

@@ -5,8 +5,8 @@
</NuxtLink>
<UColorModeImage
light="/illustrations/pro-light.svg"
dark="/illustrations/pro-dark.svg"
light="/pro/illustrations/docs-light.svg"
dark="/pro/illustrations/docs-dark.svg"
alt="Nuxt UI Pro"
loading="lazy"
class="w-full"
@@ -16,7 +16,7 @@
<div class="inline-flex gap-1.5">
<Logo class="h-4 w-auto" />
<UBadge variant="subtle" size="xs" label="Pro" class="font-semibold rounded" />
<UBadge variant="subtle" size="xs" label="Pro" class="font-semibold" />
</div>
<p class="text-sm text-gray-500 dark:text-gray-400 group-hover/ad:text-gray-700 dark:group-hover/ad:text-gray-200 mt-1 transition-colors">

View File

@@ -1,5 +1,5 @@
<template>
<UPopover mode="hover" :popper="{ strategy: 'absolute' }" :ui="{ width: 'w-[156px]' }">
<UPopover mode="hover">
<template #default="{ open }">
<UButton color="gray" variant="ghost" square :class="[open && 'bg-gray-50 dark:bg-gray-800']" aria-label="Color picker">
<UIcon name="i-heroicons-swatch-20-solid" class="w-5 h-5 text-primary-500 dark:text-primary-400" />

View File

@@ -51,9 +51,11 @@
</template>
<script setup lang="ts">
// @ts-expect-error
import { transformContent } from '@nuxt/content/transformers'
// @ts-ignore
import { useShikiHighlighter } from '@nuxtjs/mdc/runtime'
import { upperFirst, camelCase, kebabCase } from 'scule'
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
// eslint-disable-next-line vue/no-dupe-keys
const props = defineProps({
@@ -122,7 +124,6 @@ const componentProps = reactive({ ...props.props })
const { $prettier } = useNuxtApp()
const appConfig = useAppConfig()
const route = useRoute()
const highlighter = useShikiHighlighter()
let name = props.slug || `U${upperFirst(camelCase(route.params.slug[route.params.slug.length - 1]))}`
@@ -216,7 +217,6 @@ const propsToSelect = computed(() => Object.keys(componentProps).map((key) => {
// eslint-disable-next-line vue/no-dupe-keys
const code = computed(() => {
let code = `\`\`\`html
<template>
<${name}`
for (const [key, value] of Object.entries(fullProps.value)) {
if (value === 'undefined' || value === null) {
@@ -246,7 +246,7 @@ const code = computed(() => {
} else {
code += ' />'
}
code += `\n</template>
code += `
\`\`\`
`
return code
@@ -268,6 +268,8 @@ function renderObject (obj: any) {
return obj
}
const shikiHighlighter = useShikiHighlighter({})
const codeHighlighter = async (code: string, lang: string, theme: any, highlights: number[]) => shikiHighlighter.getHighlightedAST(code, lang, theme, { highlights })
const { data: ast } = await useAsyncData(
`${name}-ast-${JSON.stringify({ props: componentProps, slots: props.slots, code: props.code })}`,
async () => {
@@ -281,7 +283,7 @@ const { data: ast } = await useAsyncData(
return transformContent('content:_markdown.md', formatted, {
markdown: {
highlight: {
highlighter,
highlighter: codeHighlighter,
theme: {
light: 'material-theme-lighter',
default: 'material-theme',

View File

@@ -12,7 +12,7 @@
<ContentSlot v-if="$slots.default" :use="$slots.default" />
</div>
<template v-if="hasCode">
<slot v-if="$slots.code" name="code" />
<ContentSlot v-if="$slots.code" :use="$slots.code" />
<ContentRenderer v-else :value="ast" class="[&>div>pre]:!rounded-t-none [&>div>pre]:!mt-0" />
</template>
</div>
@@ -21,8 +21,10 @@
<script setup lang="ts">
import { camelCase } from 'scule'
import { fetchContentExampleCode } from '~/composables/useContentExamplesCode'
// @ts-expect-error
import { transformContent } from '@nuxt/content/transformers'
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
// @ts-ignore
import { useShikiHighlighter } from '@nuxtjs/mdc/runtime'
const props = defineProps({
component: {
@@ -76,14 +78,15 @@ if (['command-palette-theme-algolia', 'command-palette-theme-raycast', 'vertical
const instance = getCurrentInstance()
const camelName = camelCase(component)
const data = await fetchContentExampleCode(camelName)
const highlighter = useShikiHighlighter()
const hasCode = computed(() => !props.hiddenCode && (data?.code || instance.slots.code))
const shikiHighlighter = useShikiHighlighter({})
const codeHighlighter = async (code: string, lang: string, theme: any, highlights: number[]) => shikiHighlighter.getHighlightedAST(code, lang, theme, { highlights })
const { data: ast } = await useAsyncData(`content-example-${camelName}-ast`, () => transformContent('content:_markdown.md', `\`\`\`vue\n${data?.code ?? ''}\n\`\`\``, {
markdown: {
highlight: {
highlighter,
highlighter: codeHighlighter,
theme: {
light: 'material-theme-lighter',
default: 'material-theme',

View File

@@ -3,10 +3,9 @@
</template>
<script setup lang="ts">
// @ts-expect-error
import { transformContent } from '@nuxt/content/transformers'
import { upperFirst, camelCase } from 'scule'
import json5 from 'json5'
import { useShikiHighlighter } from '~/composables/useShikiHighlighter'
import * as config from '#ui/ui.config'
const props = defineProps({
@@ -17,7 +16,6 @@ const props = defineProps({
})
const route = useRoute()
const highlighter = useShikiHighlighter()
// eslint-disable-next-line vue/no-dupe-keys
const slug = props.slug || route.params.slug[route.params.slug.length - 1]
const camelName = camelCase(slug)
@@ -26,18 +24,15 @@ const name = `U${upperFirst(camelName)}`
const preset = config[camelName]
const { data: ast } = await useAsyncData(`${name}-preset`, () => transformContent('content:_markdown.md', `
\`\`\`yml
${json5.stringify(preset, null, 2)}
\`\`\`json
${JSON.stringify(preset, null, 2)}
\`\`\`\
`, {
markdown: {
highlight: {
highlighter,
theme: {
light: 'material-theme-lighter',
default: 'material-theme',
dark: 'material-theme-palenight'
}
highlight: {
theme: {
light: 'material-theme-lighter',
default: 'material-theme',
dark: 'material-theme-palenight'
}
}
}))

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [{
label: 'Getting Started',
icon: 'i-heroicons-information-circle',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [{
label: 'Getting Started',
icon: 'i-heroicons-information-circle',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [{
label: 'Getting Started',
icon: 'i-heroicons-information-circle',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const links = [{
label: 'Home',
icon: 'i-heroicons-home',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const links = [{
label: 'Home',
to: '/'

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const links = [{
label: 'Home',
icon: 'i-heroicons-home',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const links = [{
label: 'Home',
to: '/'

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/600/800?random=1',
'https://picsum.photos/600/800?random=2',
'https://picsum.photos/600/800?random=3',
'https://picsum.photos/600/800?random=4',
'https://picsum.photos/600/800?random=5',
'https://picsum.photos/600/800?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items">
<img :src="item" width="300" height="400" draggable="false">
</UCarousel>
</template>

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/1920/1080?random=1',
'https://picsum.photos/1920/1080?random=2',
'https://picsum.photos/1920/1080?random=3',
'https://picsum.photos/1920/1080?random=4',
'https://picsum.photos/1920/1080?random=5',
'https://picsum.photos/1920/1080?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full' }" class="rounded-lg overflow-hidden" arrows>
<img :src="item" class="w-full" draggable="false">
</UCarousel>
</template>

View File

@@ -1,35 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/600/800?random=1',
'https://picsum.photos/600/800?random=2',
'https://picsum.photos/600/800?random=3',
'https://picsum.photos/600/800?random=4',
'https://picsum.photos/600/800?random=5',
'https://picsum.photos/600/800?random=6'
]
</script>
<template>
<UCarousel
v-slot="{ item }"
:items="items"
:ui="{
item: 'basis-full',
container: 'rounded-lg'
}"
:prev-button="{
color: 'gray',
icon: 'i-heroicons-arrow-left-20-solid',
class: '-left-12'
}"
:next-button="{
color: 'gray',
icon: 'i-heroicons-arrow-right-20-solid',
class: '-right-12'
}"
arrows
class="w-64 mx-auto"
>
<img :src="item" class="w-full" draggable="false">
</UCarousel>
</template>

View File

@@ -1,37 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/1920/1080?random=1',
'https://picsum.photos/1920/1080?random=2',
'https://picsum.photos/1920/1080?random=3',
'https://picsum.photos/1920/1080?random=4',
'https://picsum.photos/1920/1080?random=5',
'https://picsum.photos/1920/1080?random=6'
]
const carouselRef = ref()
onMounted(() => {
setInterval(() => {
if (!carouselRef.value) return
if (carouselRef.value.page === carouselRef.value.pages) {
return carouselRef.value.select(0)
}
carouselRef.value.next()
}, 3000)
})
</script>
<template>
<UCarousel
ref="carouselRef"
v-slot="{ item }"
:items="items"
:ui="{ item: 'basis-full' }"
class="rounded-lg overflow-hidden"
indicators
>
<img :src="item" class="w-full" draggable="false">
</UCarousel>
</template>

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/1920/1080?random=1',
'https://picsum.photos/1920/1080?random=2',
'https://picsum.photos/1920/1080?random=3',
'https://picsum.photos/1920/1080?random=4',
'https://picsum.photos/1920/1080?random=5',
'https://picsum.photos/1920/1080?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full' }" class="rounded-lg overflow-hidden" indicators>
<img :src="item" class="w-full" draggable="false">
</UCarousel>
</template>

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/600/600?random=1',
'https://picsum.photos/600/600?random=2',
'https://picsum.photos/600/600?random=3',
'https://picsum.photos/600/600?random=4',
'https://picsum.photos/600/600?random=5',
'https://picsum.photos/600/600?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full md:basis-1/2 lg:basis-1/3' }" indicators class="rounded-lg overflow-hidden">
<img :src="item" class="w-full" draggable="false">
</UCarousel>
</template>

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/600/600?random=1',
'https://picsum.photos/600/600?random=2',
'https://picsum.photos/600/600?random=3',
'https://picsum.photos/600/600?random=4',
'https://picsum.photos/600/600?random=5',
'https://picsum.photos/600/600?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full md:basis-1/2 lg:basis-1/3' }">
<img :src="item" class="w-full" draggable="false">
</UCarousel>
</template>

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/600/800?random=1',
'https://picsum.photos/600/800?random=2',
'https://picsum.photos/600/800?random=3',
'https://picsum.photos/600/800?random=4',
'https://picsum.photos/600/800?random=5',
'https://picsum.photos/600/800?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full' }" class="w-64 mx-auto rounded-lg overflow-hidden">
<img :src="item" class="w-full" draggable="false">
</UCarousel>
</template>

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/1920/1080?random=1',
'https://picsum.photos/1920/1080?random=2',
'https://picsum.photos/1920/1080?random=3',
'https://picsum.photos/1920/1080?random=4',
'https://picsum.photos/1920/1080?random=5',
'https://picsum.photos/1920/1080?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'basis-full' }" class="rounded-lg overflow-hidden">
<img :src="item" class="w-full" draggable="false">
</UCarousel>
</template>

View File

@@ -1,31 +0,0 @@
<script setup lang="ts">
const items = [{
name: 'Sébastien Chopin',
to: 'https://github.com/Atinux',
avatar: { src: 'https://ipx.nuxt.com/f_auto,s_192x192/gh_avatar/atinux' }
}, {
name: 'Pooya Parsa',
to: 'https://github.com/pi0',
avatar: { src: 'https://ipx.nuxt.com/f_auto,s_192x192/gh_avatar/pi0' }
}, {
name: 'Daniel Roe',
to: 'https://github.com/danielroe',
avatar: { src: 'https://ipx.nuxt.com/f_auto,s_192x192/gh_avatar/danielroe' }
}, {
name: 'Anthony Fu',
to: 'https://github.com/antfu',
avatar: { src: 'https://ipx.nuxt.com/f_auto,s_192x192/gh_avatar/antfu' }
}]
</script>
<template>
<UCarousel v-slot="{ item, index }" :items="items" :ui="{ item: 'w-full' }">
<div class="text-center mx-auto">
<img :src="item.avatar.src" :alt="item.name" class="rounded-full w-48 h-48 mb-2" draggable="false">
<p class="font-semibold">
{{ index + 1 }}. {{ item.name }}
</p>
</div>
</UCarousel>
</template>

View File

@@ -1,33 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/600/800?random=1',
'https://picsum.photos/600/800?random=2',
'https://picsum.photos/600/800?random=3',
'https://picsum.photos/600/800?random=4',
'https://picsum.photos/600/800?random=5',
'https://picsum.photos/600/800?random=6'
]
</script>
<template>
<UCarousel
:items="items"
:ui="{
item: 'basis-full',
container: 'rounded-lg',
indicators: {
wrapper: 'relative bottom-0 mt-4'
}
}"
indicators
class="w-64 mx-auto"
>
<template #default="{ item }">
<img :src="item" class="w-full" draggable="false">
</template>
<template #indicator="{ onClick, page, active }">
<UButton :label="String(page)" :variant="active ? 'solid' : 'outline'" size="2xs" class="rounded-full min-w-6 justify-center" @click="onClick(page)" />
</template>
</UCarousel>
</template>

View File

@@ -1,38 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/600/800?random=1',
'https://picsum.photos/600/800?random=2',
'https://picsum.photos/600/800?random=3',
'https://picsum.photos/600/800?random=4',
'https://picsum.photos/600/800?random=5',
'https://picsum.photos/600/800?random=6'
]
</script>
<template>
<UCarousel
:items="items"
:ui="{
item: 'basis-full',
container: 'rounded-lg'
}"
arrows
class="w-64 mx-auto"
>
<template #default="{ item }">
<img :src="item" class="w-full" draggable="false">
</template>
<template #prev="{ onClick, disabled }">
<button :disabled="disabled" @click="onClick">
Prev
</button>
</template>
<template #next="{ onClick, disabled }">
<button :disabled="disabled" @click="onClick">
Next
</button>
</template>
</UCarousel>
</template>

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/400/600?random=1',
'https://picsum.photos/400/600?random=2',
'https://picsum.photos/400/600?random=3',
'https://picsum.photos/400/600?random=4',
'https://picsum.photos/400/600?random=5',
'https://picsum.photos/400/600?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'snap-end' }">
<img :src="item" width="200" height="300" draggable="false">
</UCarousel>
</template>

View File

@@ -1,16 +0,0 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/400/600?random=1',
'https://picsum.photos/400/600?random=2',
'https://picsum.photos/400/600?random=3',
'https://picsum.photos/400/600?random=4',
'https://picsum.photos/400/600?random=5',
'https://picsum.photos/400/600?random=6'
]
</script>
<template>
<UCarousel v-slot="{ item }" :items="items" :ui="{ item: 'snap-start' }">
<img :src="item" width="200" height="300" draggable="false">
</UCarousel>
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const selected = ref(true)
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [{
name: 'messages',
icon: 'i-heroicons-chat-bubble-oval-left',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const groups = [{
key: 'users',
label: q => q && `Users matching “${q}”...`,
@@ -7,7 +7,7 @@ const groups = [{
return []
}
const users = await $fetch<any[]>('https://jsonplaceholder.typicode.com/users', { params: { q } })
const users = await $fetch('https://jsonplaceholder.typicode.com/users', { params: { q } })
return users.map(user => ({ id: user.id, label: user.name, suffix: user.email }))
}

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = [
{ id: 1, label: 'Wade Cooper' },
{ id: 2, label: 'Arlene Mccoy' },

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = [
{ id: 1, label: 'Wade Cooper', child: true },
{ id: 2, label: 'Arlene Mccoy' },

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const router = useRouter()
const toast = useToast()

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const isOpen = ref(false)
const people = [

View File

@@ -1,11 +1,8 @@
<script setup lang="ts">
import type { NavItem, ParsedContent } from '@nuxt/content/dist/runtime/types'
import type { Button } from '#ui/types'
<script setup>
const commandPaletteRef = ref()
const navigation = inject<Ref<NavItem[]>>('navigation')
const files = inject<Ref<ParsedContent[]>>('files')
const navigation = inject('navigation')
const files = inject('files')
const groups = computed(() => navigation.value.map(item => ({
key: item._path,
@@ -66,8 +63,8 @@ const ui = {
ref="commandPaletteRef"
:groups="groups"
:ui="ui"
:close-button="(closeButton as Button)"
:empty-state="(emptyState as any)"
:close-button="closeButton"
:empty-state="emptyState"
:autoselect="false"
command-attribute="title"
:fuse="{

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const commandPaletteRef = ref()
const suggestions = [

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const { x, y } = useMouse()
const { y: windowY } = useWindowScroll()

View File

@@ -1,15 +1,16 @@
<script setup lang="ts">
import { format } from 'date-fns'
<script setup>
const date = ref(new Date())
const label = computed(() => date.value.toLocaleDateString('en-us', { weekday: 'long', year: 'numeric', month: 'short', day: 'numeric' })
)
</script>
<template>
<UPopover :popper="{ placement: 'bottom-start' }">
<UButton icon="i-heroicons-calendar-days-20-solid" :label="format(date, 'd MMM, yyy')" />
<UButton icon="i-heroicons-calendar-days-20-solid" :label="label" />
<template #panel="{ close }">
<DatePicker v-model="date" @close="close" />
<LazyDatePicker v-model="date" @close="close" />
</template>
</UPopover>
</template>

View File

@@ -1,48 +0,0 @@
<script setup lang="ts">
import { sub, format, isSameDay, type Duration } from 'date-fns'
const ranges = [
{ label: 'Last 7 days', duration: { days: 7 } },
{ label: 'Last 14 days', duration: { days: 14 } },
{ label: 'Last 30 days', duration: { days: 30 } },
{ label: 'Last 3 months', duration: { months: 3 } },
{ label: 'Last 6 months', duration: { months: 6 } },
{ label: 'Last year', duration: { years: 1 } }
]
const selected = ref({ start: sub(new Date(), { days: 14 }), end: new Date() })
function isRangeSelected (duration: Duration) {
return isSameDay(selected.value.start, sub(new Date(), duration)) && isSameDay(selected.value.end, new Date())
}
function selectRange (duration: Duration) {
selected.value = { start: sub(new Date(), duration), end: new Date() }
}
</script>
<template>
<UPopover :popper="{ placement: 'bottom-start' }">
<UButton icon="i-heroicons-calendar-days-20-solid">
{{ format(selected.start, 'd MMM, yyy') }} - {{ format(selected.end, 'd MMM, yyy') }}
</UButton>
<template #panel="{ close }">
<div class="flex items-center divide-x divide-gray-200 dark:divide-gray-800">
<div class="flex flex-col py-4">
<UButton
v-for="(range, index) in ranges"
:key="index"
:label="range.label"
color="gray"
variant="ghost"
class="rounded-none px-6"
:class="[isRangeSelected(range.duration) ? 'bg-gray-100 dark:bg-gray-800' : 'hover:bg-gray-50 dark:hover:bg-gray-800/50']"
@click="selectRange(range.duration)"
/>
</div>
<DatePicker v-model="selected" @close="close" />
</div>
</template>
</UPopover>
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const form = reactive({ email: 'mail@example.com', password: 'password' })
</script>
@@ -17,7 +17,7 @@ const form = reactive({ email: 'mail@example.com', password: 'password' })
<UButton label="Login" color="gray" block />
</div>
<UDivider label="OR" orientation="vertical" />
<UDivider label="OR" color="gray" orientation="vertical" />
<div class="space-y-4 flex flex-col justify-center">
<UButton color="black" label="Login with GitHub" icon="i-simple-icons-github" block />
@@ -37,7 +37,7 @@ const form = reactive({ email: 'mail@example.com', password: 'password' })
<UButton label="Login" color="gray" block />
<UDivider label="OR" />
<UDivider label="OR" color="gray" />
<UButton color="black" label="Login with GitHub" icon="i-simple-icons-github" block />
<UButton color="black" label="Login with Google" icon="i-simple-icons-google" block />

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [
[{
label: 'Profile',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [
[{
label: 'Profile',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [
[{
label: 'Profile',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [
[{
label: 'Profile',

View File

@@ -1,22 +0,0 @@
<script setup lang="ts">
const items = [
[{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
}
}]
]
const open = ref(true)
defineShortcuts({
o: () => open.value = !open.value
})
</script>
<template>
<UDropdown v-model:open="open" :items="items" :popper="{ placement: 'bottom-start' }">
<UButton color="white" label="Options" trailing-icon="i-heroicons-chevron-down-20-solid" />
</UDropdown>
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [
[{
label: 'Profile',

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const items = [
[{
label: 'ben@example.com',

View File

@@ -10,8 +10,8 @@ const schema = objectAsync({
type Schema = Input<typeof schema>
const state = reactive({
email: '',
password: ''
email: undefined,
password: undefined
})
async function onSubmit (event: FormSubmitEvent<Schema>) {

View File

@@ -6,7 +6,7 @@
</UForm>
</template>
<script setup lang="ts">
<script setup>
import { z } from 'zod'
const schema = z.object({

View File

@@ -1,27 +0,0 @@
<script setup lang="ts">
const route = useRoute()
const links = [{
label: 'Profile',
avatar: {
src: 'https://avatars.githubusercontent.com/u/739984?v=4'
},
badge: 100
}, {
label: 'Installation',
icon: 'i-heroicons-home',
to: '/getting-started/installation'
}, {
label: 'Horizontal Navigation',
icon: 'i-heroicons-chart-bar',
to: `${route.path.startsWith('/dev') ? '/dev' : ''}/components/horizontal-navigation`
}, {
label: 'Command Palette',
icon: 'i-heroicons-command-line',
to: '/components/command-palette'
}]
</script>
<template>
<UHorizontalNavigation :links="links" class="border-b border-gray-200 dark:border-gray-800" />
</template>

View File

@@ -1,22 +0,0 @@
<script setup lang="ts">
const route = useRoute()
const links = [{
label: 'Horizontal Navigation',
to: `${route.path.startsWith('/dev') ? '/dev' : ''}/components/horizontal-navigation`
}, {
label: 'Command Palette',
to: '/components/command-palette'
}, {
label: 'Table',
to: '/components/table'
}]
</script>
<template>
<UHorizontalNavigation :links="links">
<template #default="{ link }">
<span class="group-hover:text-primary relative">{{ link.label }}</span>
</template>
</UHorizontalNavigation>
</template>

View File

@@ -1,29 +0,0 @@
<script setup lang="ts">
const route = useRoute()
const links = [
[{
label: 'Installation',
icon: 'i-heroicons-home',
to: '/getting-started/installation'
}, {
label: 'Horizontal Navigation',
icon: 'i-heroicons-chart-bar',
to: `${route.path.startsWith('/dev') ? '/dev' : ''}/components/horizontal-navigation`
}, {
label: 'Command Palette',
icon: 'i-heroicons-command-line',
to: '/components/command-palette'
}], [{
label: 'Examples',
icon: 'i-heroicons-light-bulb'
}, {
label: 'Help',
icon: 'i-heroicons-question-mark-circle'
}]
]
</script>
<template>
<UHorizontalNavigation :links="links" class="border-b border-gray-200 dark:border-gray-800" />
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const value = ref('')
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref(people[0])

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = []
const selected = ref()

View File

@@ -1,6 +1,4 @@
<script setup lang="ts">
import type { Avatar } from '#ui/types'
<script setup>
const people = [{
id: 'benjamincanac',
label: 'benjamincanac',
@@ -31,8 +29,8 @@ const selected = ref(people[0])
<template>
<UInputMenu v-model="selected" :options="people">
<template #leading>
<UIcon v-if="selected.icon" :name="(selected.icon as string)" class="w-4 h-4 mx-0.5" />
<UAvatar v-else-if="selected.avatar" v-bind="(selected.avatar as Avatar)" size="3xs" class="mx-0.5" />
<UIcon v-if="selected.icon" :name="selected.icon" class="w-4 h-4 mx-0.5" />
<UAvatar v-else-if="selected.avatar" v-bind="selected.avatar" size="3xs" class="mx-0.5" />
</template>
</UInputMenu>
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = [{
id: 1,
name: 'Wade Cooper'
@@ -13,14 +13,14 @@ const people = [{
name: 'Tom Cook'
}]
const selected = ref(people[0].id)
const selected = ref(people[0].name)
</script>
<template>
<UInputMenu
v-model="selected"
:options="people"
value-attribute="id"
value-attribute="name"
option-attribute="name"
/>
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref(people[0])

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = [
{ name: 'Wade Cooper', online: true },
{ name: 'Arlene Mccoy', online: false },

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref(people[0])

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref(people[0])

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref(people[0])

View File

@@ -1,26 +0,0 @@
<script setup lang="ts">
const loading = ref(false)
const selected = ref()
async function search (q: string) {
loading.value = true
const users = await $fetch<any[]>('https://jsonplaceholder.typicode.com/users', { params: { q } })
loading.value = false
return users
}
</script>
<template>
<UInputMenu
v-model="selected"
:search="search"
:loading="loading"
placeholder="Search for a user..."
option-attribute="name"
trailing
by="id"
/>
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const options = [
{ id: 1, name: 'Wade Cooper', colors: ['red', 'yellow'] },
{ id: 2, name: 'Arlene Mccoy', colors: ['blue', 'yellow'] },

View File

@@ -1,15 +0,0 @@
<script setup lang="ts">
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const selected = ref()
const query = ref('Wade')
</script>
<template>
<UInputMenu
v-model="selected"
v-model:query="query"
:options="people"
placeholder="Select a person"
/>
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const { metaSymbol } = useShortcuts()
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const used = ref(84.2)
const total = 238.42

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const used = ref(84.2)
const total = 238.42

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const isOpen = ref(false)
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const isOpen = ref(false)
</script>

View File

@@ -1,17 +0,0 @@
<script lang="ts" setup>
defineProps({
count: {
type: Number,
default: 0
}
})
</script>
<template>
<UModal>
<UCard>
<p>This modal was opened programmatically !</p>
<p>Count: {{ count }}</p>
</UCard>
</UModal>
</template>

View File

@@ -1,17 +0,0 @@
<script setup lang="ts">
import { ModalExampleComponent } from '#components'
const modal = useModal()
const count = ref(0)
function openModal () {
count.value += 1
modal.open(ModalExampleComponent, {
count: count.value
})
}
</script>
<template>
<UButton label="Reveal modal" @click="openModal" />
</template>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const isOpen = ref(false)
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const isOpen = ref(false)
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const isOpen = ref(false)
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const isOpen = ref(false)
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const toast = useToast()
const actions = ref([{

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const toast = useToast()
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const toast = useToast()
function onCallback () {

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const toast = useToast()
function onClick () {

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const toast = useToast()
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const page = ref(1)
const items = ref(Array(55))
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const page = ref(1)
const items = ref(Array(55))
</script>

View File

@@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup>
const page = ref(1)
const items = ref(Array(55))
</script>

View File

@@ -0,0 +1,68 @@
<script setup>
const page = ref(1)
const items = ref(Array(55))
</script>
<template>
<div class="w-full divide-y divide-gray-200 dark:divide-gray-700 space-y-4">
<div class="flex flex-wrap gap-1 justify-between w-full">
<div dir="ltr">
<UInput
icon="i-heroicons-magnifying-glass-20-solid"
size="sm"
color="white"
placeholder="Search..."
:trailing="false"
/>
</div>
<div dir="rtl">
<UInput
icon="i-heroicons-magnifying-glass-20-solid"
size="sm"
color="white"
placeholder="ابحث..."
:trailing="false"
/>
</div>
</div>
<div class="flex flex-wrap gap-1 justify-between w-full pt-4">
<div dir="ltr">
<UPagination
v-model="page"
:total="items.length"
:prev-button="{
icon: 'i-heroicons-arrow-small-left-20-solid',
label: 'Prev',
color: 'gray'
}"
:next-button="{
icon: 'i-heroicons-arrow-small-right-20-solid',
trailing: true,
label: 'Next',
color: 'gray'
}"
/>
</div>
<div dir="rtl">
<UPagination
v-model="page"
:total="items.length"
:prev-button="{
icon: 'i-heroicons-arrow-small-left-20-solid',
label: 'السابق',
color: 'gray'
}"
:next-button="{
icon: 'i-heroicons-arrow-small-right-20-solid',
trailing: true,
label: 'التالي',
color: 'gray'
}"
/>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,21 @@
<script setup>
const page = ref(1)
const items = ref(Array(55))
</script>
<template>
<UPagination
v-model="page"
:total="items.length"
:ui="{
wrapper: 'flex items-center gap-1',
rounded: '!rounded-full min-w-[32px] justify-center'
}"
:prev-button="null"
:next-button="{
icon: 'i-heroicons-arrow-small-right-20-solid',
color: 'primary',
variant: 'outline'
}"
/>
</template>

Some files were not shown because too many files have changed in this diff Show More