@nexxtmove/ui 1.33.0 → 1.35.0
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/dist/components/atoms/FloatingPanel/FloatingPanel.vue.d.ts +48 -7
- package/dist/components/atoms/PickerItem/PickerItem.vue.d.ts +40 -0
- package/dist/components/atoms/PickerPreview/PickerPreview.vue.d.ts +29 -0
- package/dist/components/editor/molecules/EditorColor/EditorColor.vue.d.ts +4 -1
- package/dist/components/editor/molecules/EditorRadius/EditorRadius.vue.d.ts +2 -2
- package/dist/components/molecules/PickerGroup/PickerGroup.vue.d.ts +32 -0
- package/dist/components/molecules/PickerList/PickerList.vue.d.ts +107 -0
- package/dist/components/organisms/ColorPicker/ColorPicker.vue.d.ts +8 -1
- package/dist/components/organisms/PickerPanel/PickerPanel.vue.d.ts +93 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +2387 -1612
- package/dist/nuxt.js +5 -0
- package/package.json +1 -1
- package/src/components/atoms/FloatingPanel/FloatingPanel.vue +280 -20
- package/src/components/atoms/PickerItem/PickerItem.vue +113 -0
- package/src/components/atoms/PickerPreview/PickerPreview.vue +99 -0
- package/src/components/editor/molecules/EditorColor/EditorColor.vue +8 -1
- package/src/components/molecules/PickerGroup/PickerGroup.vue +107 -0
- package/src/components/molecules/PickerList/PickerList.vue +649 -0
- package/src/components/organisms/ColorPicker/ColorPicker.vue +86 -10
- package/src/components/organisms/PickerPanel/PickerPanel.vue +267 -0
- package/src/components.json +5 -0
- package/src/index.ts +9 -0
|
@@ -14,10 +14,11 @@ export type EditorColorProperty = 'bg' | 'text'
|
|
|
14
14
|
*/
|
|
15
15
|
export type EditorColorValue = `${EditorColorProperty}-[#${string}]`
|
|
16
16
|
|
|
17
|
-
/** Overridable copy of the picker. Every key is optional. */
|
|
18
17
|
export interface EditorColorMessages {
|
|
19
18
|
/** Text shown while no colour is set. Defaults to `'Kies kleur...'`. */
|
|
20
19
|
placeholder?: string
|
|
20
|
+
/** Label shown above reusable colours. */
|
|
21
|
+
suggestionsLabel?: string
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export interface NexxtEditorColorProps {
|
|
@@ -44,10 +45,13 @@ export interface NexxtEditorColorProps {
|
|
|
44
45
|
* defaults of the others. Copy is never translated inside the component.
|
|
45
46
|
*/
|
|
46
47
|
messages?: EditorColorMessages
|
|
48
|
+
/** Hex colours available inside the picker panel as one-click suggestions. */
|
|
49
|
+
suggestions?: string[]
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
const DEFAULT_MESSAGES = {
|
|
50
53
|
placeholder: 'Kies kleur...',
|
|
54
|
+
suggestionsLabel: 'Gebruikte kleuren',
|
|
51
55
|
} satisfies Required<EditorColorMessages>
|
|
52
56
|
|
|
53
57
|
/**
|
|
@@ -72,6 +76,7 @@ const {
|
|
|
72
76
|
switchable = false,
|
|
73
77
|
property = 'bg',
|
|
74
78
|
messages,
|
|
79
|
+
suggestions = [],
|
|
75
80
|
} = defineProps<NexxtEditorColorProps>()
|
|
76
81
|
|
|
77
82
|
/**
|
|
@@ -150,6 +155,8 @@ watch(
|
|
|
150
155
|
:formats="['hex']"
|
|
151
156
|
:show-alpha="false"
|
|
152
157
|
:placeholder="copy.placeholder"
|
|
158
|
+
:suggestions="{ hex: suggestions }"
|
|
159
|
+
:suggestions-label="copy.suggestionsLabel"
|
|
153
160
|
/>
|
|
154
161
|
</NexxtEditorSettingsBlock>
|
|
155
162
|
</template>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, useId } from 'vue'
|
|
3
|
+
import { usePreferredReducedMotion } from '@vueuse/core'
|
|
4
|
+
import NexxtIcon from '../../atoms/Icon/Icon.vue'
|
|
5
|
+
|
|
6
|
+
interface NexxtPickerGroupProps {
|
|
7
|
+
/** Heading of the group, and the accessible name of its `role="group"`. */
|
|
8
|
+
label: string
|
|
9
|
+
/**
|
|
10
|
+
* Whether the heading folds the group. `false` turns the heading into a plain label: no
|
|
11
|
+
* chevron, no click handler, no `aria-expanded`.
|
|
12
|
+
*/
|
|
13
|
+
collapsible?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
defineOptions({ name: 'NexxtPickerGroup' })
|
|
17
|
+
|
|
18
|
+
const { label, collapsible = true } = defineProps<NexxtPickerGroupProps>()
|
|
19
|
+
|
|
20
|
+
/** Whether the options are shown. A closed group has its options out of the DOM. */
|
|
21
|
+
const open = defineModel<boolean>('open', { default: true })
|
|
22
|
+
|
|
23
|
+
defineSlots<{
|
|
24
|
+
/** The options: `NexxtPickerItem`s, or anything else with `role="option"`. */
|
|
25
|
+
default(): unknown
|
|
26
|
+
}>()
|
|
27
|
+
|
|
28
|
+
const headingId = useId()
|
|
29
|
+
|
|
30
|
+
const preferredMotion = usePreferredReducedMotion()
|
|
31
|
+
// `motion-reduce:transition-none` alone leaves Vue reading the 120ms off the leaving wrapper, so
|
|
32
|
+
// the options of a "closed" group would linger; without CSS mode they go in the same patch
|
|
33
|
+
const reduced = computed(() => preferredMotion.value === 'reduce')
|
|
34
|
+
|
|
35
|
+
const HEADING_CLASSES = {
|
|
36
|
+
base: 'flex h-7 items-center gap-1.5 rounded-lg px-2 extra-small-semibold tracking-wide text-gray-700 uppercase select-none',
|
|
37
|
+
collapsible: 'cursor-pointer hover:bg-gray-50',
|
|
38
|
+
static: 'cursor-default',
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const CHEVRON_CLASSES = {
|
|
42
|
+
base: 'extra-small-normal transition-transform motion-reduce:transition-none',
|
|
43
|
+
open: 'duration-160 ease-out',
|
|
44
|
+
closed: '-rotate-90 duration-120 ease-in',
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const headingClass = computed(() => [
|
|
48
|
+
HEADING_CLASSES.base,
|
|
49
|
+
collapsible ? HEADING_CLASSES.collapsible : HEADING_CLASSES.static,
|
|
50
|
+
])
|
|
51
|
+
|
|
52
|
+
const chevronClass = computed(() => [
|
|
53
|
+
CHEVRON_CLASSES.base,
|
|
54
|
+
open.value ? CHEVRON_CLASSES.open : CHEVRON_CLASSES.closed,
|
|
55
|
+
])
|
|
56
|
+
|
|
57
|
+
// Bound through `v-on`, so a static heading has no click handler at all
|
|
58
|
+
const headingListeners = computed(() =>
|
|
59
|
+
collapsible ? { click: () => (open.value = !open.value) } : {},
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
// Options on their way out can no longer be clicked, and assistive tech skips them
|
|
63
|
+
const onBeforeLeave = (el: Element) => el.setAttribute('inert', '')
|
|
64
|
+
</script>
|
|
65
|
+
|
|
66
|
+
<template>
|
|
67
|
+
<div
|
|
68
|
+
role="group"
|
|
69
|
+
:aria-labelledby="headingId"
|
|
70
|
+
:aria-expanded="collapsible ? open : undefined"
|
|
71
|
+
class="flex flex-col not-first:mt-2"
|
|
72
|
+
>
|
|
73
|
+
<!-- Not a button and not a tab stop: a listbox may only hold options and groups. The keyboard
|
|
74
|
+
folds a group with ←/→ from the listbox. `mousedown.prevent` keeps focus where it was. -->
|
|
75
|
+
<div role="presentation" :class="headingClass" v-on="headingListeners" @mousedown.prevent>
|
|
76
|
+
<span
|
|
77
|
+
v-if="collapsible"
|
|
78
|
+
class="flex size-3 shrink-0 items-center justify-center text-gray-700"
|
|
79
|
+
>
|
|
80
|
+
<NexxtIcon name="chevron-down" aria-hidden="true" :class="chevronClass" />
|
|
81
|
+
</span>
|
|
82
|
+
<span :id="headingId">{{ label }}</span>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<!-- No row class on the wrapper itself: after entering it is plain `auto`, so a base class
|
|
86
|
+
never fights the from/to classes -->
|
|
87
|
+
<Transition
|
|
88
|
+
:css="!reduced"
|
|
89
|
+
enter-active-class="transition-[grid-template-rows,opacity] duration-160 ease-out motion-reduce:transition-none"
|
|
90
|
+
enter-from-class="grid-rows-[0fr] opacity-0"
|
|
91
|
+
enter-to-class="grid-rows-[1fr] opacity-100"
|
|
92
|
+
leave-active-class="transition-[grid-template-rows,opacity] duration-120 ease-in motion-reduce:transition-none"
|
|
93
|
+
leave-from-class="grid-rows-[1fr] opacity-100"
|
|
94
|
+
leave-to-class="grid-rows-[0fr] opacity-0"
|
|
95
|
+
@before-leave="onBeforeLeave"
|
|
96
|
+
>
|
|
97
|
+
<div v-if="open" class="grid">
|
|
98
|
+
<div class="min-h-0 overflow-hidden">
|
|
99
|
+
<!-- Padding here rather than on the clipping layer, so nothing is left at 0fr -->
|
|
100
|
+
<div class="flex flex-col gap-0.5 pt-0.5">
|
|
101
|
+
<slot />
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</Transition>
|
|
106
|
+
</div>
|
|
107
|
+
</template>
|