Compare commits

...

22 Commits

Author SHA1 Message Date
Benjamin Canac
56230ea915 chore(release): 1.2.11 2023-05-04 11:01:28 +02:00
Benjamin Canac
126b5fcfd4 Revert "chore(github): add v1 branch to ci dev"
This reverts commit d3536d8768.
2023-05-04 11:00:12 +02:00
Benjamin Canac
d3536d8768 chore(github): add v1 branch to ci dev 2023-05-04 10:52:54 +02:00
Sylvain Marroufin
59f62d322f fix(defineShortcuts): use useEventListener (#150) 2023-05-04 10:50:10 +02:00
Sylvain Marroufin
b85a8e7203 chore(defineShortcuts): config prop whenever more flexible (#149) 2023-05-02 14:47:31 +02:00
Benjamin Canac
8830d848fd chore(release): 1.2.10 2023-04-07 19:23:36 +02:00
Benjamin Canac
cfce1524b2 fix(CommandPalette): typecheck 2023-04-07 19:23:25 +02:00
Benjamin Canac
f845e89a76 chore(release): 1.2.9 2023-04-07 19:21:55 +02:00
Benjamin Canac
d9ca5d188a chore(CommandPalette): improve command highlight 2023-04-07 18:30:25 +02:00
Benjamin Canac
2429bcf5a7 chore(SelectCustom): right padding only when selected 2023-04-05 13:01:16 +02:00
Benjamin Canac
f45f4a3e56 chore(release): 1.2.8 2023-04-04 15:14:06 +02:00
Benjamin Canac
09e957e702 chore(deps): remove @tailwindcss/line-clamp as its included by default in tailwind 3.3 2023-04-04 13:55:38 +02:00
Benjamin Canac
1ecd7cefde chore(release): 1.2.7 2023-04-04 13:36:43 +02:00
Benjamin Canac
aafdfdb59c fix(useTimer): remaining after pause 2023-04-04 13:36:24 +02:00
Benjamin Canac
453ff6ca20 chore(release): 1.2.6 2023-04-04 11:26:00 +02:00
Benjamin Canac
55832b6b99 docs: ts ignore 2023-04-04 11:25:33 +02:00
Benjamin Canac
6b93bbe5cd chore(release): 1.2.5 2023-04-04 11:17:30 +02:00
Benjamin Canac
1402553145 chore(deps): bump 2023-04-04 11:17:14 +02:00
Benjamin Canac
5d84dfd05b chore(release): 1.2.4 2023-04-04 11:08:58 +02:00
Benjamin Canac
7dc59a05ec chore(useTimer): pass options to useTimestamp 2023-04-04 11:08:41 +02:00
Benjamin Canac
4bd994985d chore(release): 1.2.3 2023-03-22 16:21:49 +01:00
Benjamin Canac
c83d3b7147 chore(Avatar): remove useless chipVariant prop 2023-03-22 16:21:29 +01:00
11 changed files with 1007 additions and 709 deletions

View File

@@ -2,6 +2,39 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [1.2.11](https://github.com/nuxtlabs/ui/compare/v1.2.10...v1.2.11) (2023-05-04)
### Bug Fixes
* **defineShortcuts:** use `useEventListener` ([#150](https://github.com/nuxtlabs/ui/issues/150)) ([59f62d3](https://github.com/nuxtlabs/ui/commit/59f62d322f07919d16a8d35340c3aa038cd09520))
### [1.2.10](https://github.com/nuxtlabs/ui/compare/v1.2.9...v1.2.10) (2023-04-07)
### Bug Fixes
* **CommandPalette:** typecheck ([cfce152](https://github.com/nuxtlabs/ui/commit/cfce1524b209212d9ce635b61376ff0d6bc3601b))
### [1.2.9](https://github.com/nuxtlabs/ui/compare/v1.2.8...v1.2.9) (2023-04-07)
### [1.2.8](https://github.com/nuxtlabs/ui/compare/v1.2.7...v1.2.8) (2023-04-04)
### [1.2.7](https://github.com/nuxtlabs/ui/compare/v1.2.6...v1.2.7) (2023-04-04)
### Bug Fixes
* **useTimer:** remaining after pause ([aafdfdb](https://github.com/nuxtlabs/ui/commit/aafdfdb59c365c542f93703dd52b4306ac935040))
### [1.2.6](https://github.com/nuxtlabs/ui/compare/v1.2.5...v1.2.6) (2023-04-04)
### [1.2.5](https://github.com/nuxtlabs/ui/compare/v1.2.4...v1.2.5) (2023-04-04)
### [1.2.4](https://github.com/nuxtlabs/ui/compare/v1.2.3...v1.2.4) (2023-04-04)
### [1.2.3](https://github.com/nuxtlabs/ui/compare/v1.2.2...v1.2.3) (2023-03-22)
### [1.2.2](https://github.com/nuxtlabs/ui/compare/v1.2.1...v1.2.2) (2023-03-20) ### [1.2.2](https://github.com/nuxtlabs/ui/compare/v1.2.1...v1.2.2) (2023-03-20)
### [1.2.1](https://github.com/nuxtlabs/ui/compare/v1.2.0...v1.2.1) (2023-03-20) ### [1.2.1](https://github.com/nuxtlabs/ui/compare/v1.2.0...v1.2.1) (2023-03-20)

View File

@@ -10,6 +10,7 @@ export default defineNuxtConfig({
} }
} }
}, },
// @ts-ignore
modules: [ modules: [
// @ts-ignore // @ts-ignore
nuxtUI nuxtUI

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nuxthq/ui", "name": "@nuxthq/ui",
"version": "1.2.2", "version": "1.2.11",
"repository": "https://github.com/nuxtlabs/ui", "repository": "https://github.com/nuxtlabs/ui",
"license": "MIT", "license": "MIT",
"exports": { "exports": {
@@ -28,13 +28,12 @@
"@egoist/tailwindcss-icons": "^1.0.7", "@egoist/tailwindcss-icons": "^1.0.7",
"@headlessui/vue": "1.7.10", "@headlessui/vue": "1.7.10",
"@iconify-json/heroicons": "^1.1.10", "@iconify-json/heroicons": "^1.1.10",
"@nuxt/kit": "^3.3.1", "@nuxt/kit": "^3.3.3",
"@nuxtjs/color-mode": "^3.2.0", "@nuxtjs/color-mode": "^3.2.0",
"@nuxtjs/tailwindcss": "^6.6.0", "@nuxtjs/tailwindcss": "^6.6.5",
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.7",
"@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",
"@tailwindcss/line-clamp": "^0.4.2",
"@tailwindcss/typography": "^0.5.9", "@tailwindcss/typography": "^0.5.9",
"@vueuse/core": "^9.13.0", "@vueuse/core": "^9.13.0",
"@vueuse/integrations": "^9.13.0", "@vueuse/integrations": "^9.13.0",
@@ -42,18 +41,18 @@
"defu": "^6.1.2", "defu": "^6.1.2",
"fuse.js": "^6.6.2", "fuse.js": "^6.6.2",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"tailwindcss": "^3.2.7" "tailwindcss": "^3.3.1"
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/mdi": "^1.1.50", "@iconify-json/mdi": "^1.1.50",
"@nuxt/module-builder": "^0.2.1", "@nuxt/module-builder": "^0.2.1",
"@nuxtjs/eslint-config-typescript": "^12.0.0", "@nuxtjs/eslint-config-typescript": "^12.0.0",
"@types/lodash-es": "^4.17.7", "@types/lodash-es": "^4.17.7",
"@types/node": "^18.15.3", "@types/node": "^18.15.11",
"eslint": "^8.36.0", "eslint": "^8.37.0",
"nuxt": "^3.3.1", "nuxt": "^3.3.3",
"standard-version": "^9.5.0", "standard-version": "^9.5.0",
"unbuild": "^1.1.2", "unbuild": "^1.2.0",
"vue-tsc": "^1.2.0" "vue-tsc": "^1.2.0"
} }
} }

View File

@@ -136,7 +136,6 @@ export default defineNuxtModule<ModuleOptions>({
theme, theme,
plugins: [ plugins: [
require('@tailwindcss/forms'), require('@tailwindcss/forms'),
require('@tailwindcss/line-clamp'),
require('@tailwindcss/aspect-ratio'), require('@tailwindcss/aspect-ratio'),
require('@tailwindcss/typography') require('@tailwindcss/typography')
], ],

View File

@@ -38,12 +38,8 @@ const props = defineProps({
default: true default: true
}, },
chip: { chip: {
type: Boolean,
default: false
},
chipVariant: {
type: String, type: String,
default: 'primary', default: null,
validator (value: string) { validator (value: string) {
return Object.keys($ui.avatar.chip.variant).includes(value) return Object.keys($ui.avatar.chip.variant).includes(value)
} }
@@ -92,8 +88,8 @@ const avatarClass = computed(() => {
const chipClass = computed(() => { const chipClass = computed(() => {
return classNames( return classNames(
$ui.avatar.chip.base, $ui.avatar.chip.base,
$ui.avatar.chip.variant[props.chip],
$ui.avatar.chip.position[props.chipPosition], $ui.avatar.chip.position[props.chipPosition],
$ui.avatar.chip.variant[props.chipVariant],
$ui.avatar.chip.size[props.size] $ui.avatar.chip.size[props.size]
) )
}) })

View File

@@ -28,11 +28,13 @@
<div class="flex items-center gap-1.5 min-w-0" :class="{ 'opacity-50': command.disabled }"> <div class="flex items-center gap-1.5 min-w-0" :class="{ 'opacity-50': command.disabled }">
<slot :name="`${group.key}-command`" :group="group" :command="command"> <slot :name="`${group.key}-command`" :group="group" :command="command">
<span v-if="command.prefix" class="u-text-gray-400">{{ command.prefix }}</span> <span v-if="command.prefix" class="flex-shrink-0" :class="command.prefixClass || 'u-text-gray-400'">{{ command.prefix }}</span>
<span class="truncate" :class="{ 'flex-none': command.suffix || command.matches?.length }">{{ command[commandAttribute] }}</span>
<!-- eslint-disable-next-line vue/no-v-html --> <!-- eslint-disable-next-line vue/no-v-html -->
<span v-if="command.matches?.length" class="truncate" :class="{ 'flex-none': command.suffix }" v-html="highlight(command.matches[0])" /> <span v-if="command.matches?.length" class="truncate" :class="command.suffixClass || 'u-text-gray-400'" v-html="highlight(command[commandAttribute], command.matches[0])" />
<span v-else class="truncate" :class="{ 'flex-none': command.suffix }">{{ command[commandAttribute] }}</span> <span v-else-if="command.suffix" class="truncate" :class="command.suffixClass || 'u-text-gray-400'">{{ command.suffix }}</span>
<span v-if="command.suffix" class="u-text-gray-400 truncate">{{ command.suffix }}</span>
</slot> </slot>
</div> </div>
</div> </div>
@@ -87,13 +89,36 @@ const label = computed(() => {
return typeof label === 'function' ? label(props.query) : label return typeof label === 'function' ? label(props.query) : label
}) })
function highlight ({ indices, value }: { indices: number[][], value:string }, i = 1): string { function highlight (text: string, { indices, value }: { indices: number[][], value:string }): string {
const pair = indices[indices.length - i] if (text === value) {
if (!pair) { return ''
return value
} }
return `${highlight({ indices, value: value.substring(0, pair[0]) }, i + 1)}<mark>${value.substring(pair[0], pair[1] + 1)}</mark>${value.substring(pair[1] + 1)}` let content = ''
let nextUnhighlightedIndiceStartingIndex = 0
indices.forEach((indice) => {
const lastIndiceNextIndex = indice[1] + 1
const isMatched = (lastIndiceNextIndex - indice[0]) >= props.query.length
content += [
value.substring(nextUnhighlightedIndiceStartingIndex, indice[0]),
isMatched && '<mark>',
value.substring(indice[0], lastIndiceNextIndex),
isMatched && '</mark>'
].filter(Boolean).join('')
nextUnhighlightedIndiceStartingIndex = lastIndiceNextIndex
})
content += value.substring(nextUnhighlightedIndiceStartingIndex)
const index = content.indexOf('<mark>')
if (index > 60) {
content = `...${content.substring(index - 60)}`
}
return content
} }
</script> </script>

View File

@@ -1,12 +1,13 @@
import type { Ref, ComputedRef } from 'vue' import type { ComputedRef, WatchSource } from 'vue'
import { logicAnd, logicNot } from '@vueuse/math' import { logicAnd, logicNot } from '@vueuse/math'
import { computed, onMounted, onBeforeUnmount } from 'vue' import { useEventListener } from '@vueuse/core'
import { computed } from 'vue'
import { useShortcuts } from './useShortcuts' import { useShortcuts } from './useShortcuts'
export interface ShortcutConfig { export interface ShortcutConfig {
handler: Function handler: Function
usingInput?: string | boolean usingInput?: string | boolean
whenever?: Ref<Boolean>[] whenever?: WatchSource<Boolean>[]
} }
export interface ShortcutsConfig { export interface ShortcutsConfig {
@@ -52,58 +53,51 @@ export const defineShortcuts = (config: ShortcutsConfig) => {
} }
} }
onMounted(() => { // Map config to full detailled shortcuts
// Map config to full detailled shortcuts shortcuts = Object.entries(config).map(([key, shortcutConfig]) => {
shortcuts = Object.entries(config).map(([key, shortcutConfig]) => { if (!shortcutConfig) {
if (!shortcutConfig) { return null
return null }
}
// Parse key and modifiers // Parse key and modifiers
const keySplit = key.toLowerCase().split('_').map(k => k) const keySplit = key.toLowerCase().split('_').map(k => k)
let shortcut: Partial<Shortcut> = { let shortcut: Partial<Shortcut> = {
key: keySplit.filter(k => !['meta', 'ctrl', 'shift', 'alt'].includes(k)).join('_'), key: keySplit.filter(k => !['meta', 'ctrl', 'shift', 'alt'].includes(k)).join('_'),
metaKey: keySplit.includes('meta'), metaKey: keySplit.includes('meta'),
ctrlKey: keySplit.includes('ctrl'), ctrlKey: keySplit.includes('ctrl'),
shiftKey: keySplit.includes('shift'), shiftKey: keySplit.includes('shift'),
altKey: keySplit.includes('alt') altKey: keySplit.includes('alt')
} }
// Convert Meta to Ctrl for non-MacOS // Convert Meta to Ctrl for non-MacOS
if (!macOS.value && shortcut.metaKey && !shortcut.ctrlKey) { if (!macOS.value && shortcut.metaKey && !shortcut.ctrlKey) {
shortcut.metaKey = false shortcut.metaKey = false
shortcut.ctrlKey = true shortcut.ctrlKey = true
} }
// Retrieve handler function // Retrieve handler function
if (typeof shortcutConfig === 'function') { if (typeof shortcutConfig === 'function') {
shortcut.handler = shortcutConfig shortcut.handler = shortcutConfig
} else if (typeof shortcutConfig === 'object') { } else if (typeof shortcutConfig === 'object') {
shortcut = { ...shortcut, handler: shortcutConfig.handler } shortcut = { ...shortcut, handler: shortcutConfig.handler }
} }
if (!shortcut.handler) { if (!shortcut.handler) {
// eslint-disable-next-line no-console console.trace('[Shortcut] Invalid value')
console.trace('[Shortcut] Invalid value') return null
return null }
}
// Create shortcut computed // Create shortcut computed
const conditions = [] const conditions: ComputedRef<Boolean>[] = []
if (!(shortcutConfig as ShortcutConfig).usingInput) { if (!(shortcutConfig as ShortcutConfig).usingInput) {
conditions.push(logicNot(usingInput)) conditions.push(logicNot(usingInput))
} else if (typeof (shortcutConfig as ShortcutConfig).usingInput === 'string') { } else if (typeof (shortcutConfig as ShortcutConfig).usingInput === 'string') {
conditions.push(computed(() => usingInput.value === (shortcutConfig as ShortcutConfig).usingInput)) conditions.push(computed(() => usingInput.value === (shortcutConfig as ShortcutConfig).usingInput))
} }
shortcut.condition = logicAnd(...conditions, ...((shortcutConfig as ShortcutConfig).whenever || [])) shortcut.condition = logicAnd(...conditions, ...((shortcutConfig as ShortcutConfig).whenever || []))
return shortcut as Shortcut return shortcut as Shortcut
}).filter(Boolean) as Shortcut[] }).filter(Boolean) as Shortcut[]
document.addEventListener('keydown', onKeyDown) useEventListener('keydown', onKeyDown)
})
onBeforeUnmount(() => {
document.removeEventListener('keydown', onKeyDown)
})
} }

View File

@@ -1,16 +1,17 @@
import { ref, computed } from 'vue-demi' import { ref, computed } from 'vue-demi'
import { useTimestamp } from '@vueuse/core' import { useTimestamp } from '@vueuse/core'
import type { UseTimestampOptions } from '@vueuse/core'
export function useTimer (cb: (...args: unknown[]) => any, interval: number) { export function useTimer (cb: (...args: unknown[]) => any, interval: number, options?: UseTimestampOptions<true>) {
let timer: number | null = null let timer: number | null = null
const timestamp = useTimestamp({ controls: true }) const { pause: tPause, resume: tResume, timestamp } = useTimestamp({ ...(options || {}), controls: true })
const startTime = ref<number | null>(null) const startTime = ref<number | null>(null)
const remaining = computed(() => { const remaining = computed(() => {
if (!startTime.value) { if (!startTime.value) {
return return 0
} }
return interval - (timestamp.timestamp.value - startTime.value) return interval - (timestamp.value - startTime.value)
}) })
function set (...args: unknown[]) { function set (...args: unknown[]) {
@@ -37,18 +38,18 @@ export function useTimer (cb: (...args: unknown[]) => any, interval: number) {
function stop () { function stop () {
clear() clear()
timestamp.pause() tPause()
} }
function pause () { function pause () {
clear() clear()
timestamp.pause() tPause()
} }
function resume () { function resume () {
startTime.value = (startTime.value || 0) + (Date.now() - timestamp.timestamp.value)
timestamp.resume()
set() set()
tResume()
startTime.value = (startTime.value || 0) + (Date.now() - timestamp.value)
} }
start() start()

View File

@@ -224,12 +224,12 @@ export default function defaultPreset (variantColors: string[]) {
base: 'u-bg-white shadow-lg rounded-md ring-1 u-ring-gray-200 focus:outline-none overflow-y-auto py-1 max-h-60', base: 'u-bg-white shadow-lg rounded-md ring-1 u-ring-gray-200 focus:outline-none overflow-y-auto py-1 max-h-60',
input: 'relative block w-full focus:ring-transparent text-sm px-4 py-2 u-text-gray-700 border-l-0 u-bg-white border-t-0 border-r-0 u-border-gray-200 focus:u-border-gray-200', input: 'relative block w-full focus:ring-transparent text-sm px-4 py-2 u-text-gray-700 border-l-0 u-bg-white border-t-0 border-r-0 u-border-gray-200 focus:u-border-gray-200',
option: { option: {
base: 'cursor-default select-none relative py-2 pl-4 pr-10 text-sm group', base: 'cursor-default select-none relative py-2 text-sm group',
container: 'flex items-center gap-3', container: 'flex items-center gap-3',
active: 'text-white bg-primary-600', active: 'text-white bg-primary-600',
inactive: 'u-text-gray-900', inactive: 'u-text-gray-900',
selected: 'font-semibold', selected: 'font-semibold pl-4 pr-10',
unselected: 'font-normal', unselected: 'font-normal px-4',
disabled: 'cursor-not-allowed opacity-50', disabled: 'cursor-not-allowed opacity-50',
empty: 'text-sm u-text-gray-400 px-4 py-2', empty: 'text-sm u-text-gray-400 px-4 py-2',
icon: { icon: {

View File

@@ -4,7 +4,6 @@ export interface Avatar {
text: string text: string
size: string size: string
rounded: boolean rounded: boolean
chip: boolean chip: string
chipVariant: string
chipPosition: string chipPosition: string
} }

1491
yarn.lock

File diff suppressed because it is too large Load Diff