@nexxtmove/ui 1.14.0 → 1.16.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/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue.d.ts +35 -0
- package/dist/components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue.d.ts +39 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +577 -486
- package/dist/nuxt.js +5 -3
- package/package.json +8 -8
- package/src/components/atoms/Switch/Switch.vue +8 -1
- package/src/components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue +83 -0
- package/src/components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue +73 -0
- package/src/components.json +3 -1
- package/src/index.ts +6 -0
- package/src/nuxt.ts +15 -2
package/dist/nuxt.js
CHANGED
|
@@ -63,7 +63,9 @@ var s = {
|
|
|
63
63
|
NexxtTimelinePhaseblock: "components/organisms/TimelinePhaseblock/TimelinePhaseblock.vue",
|
|
64
64
|
NexxtTimelineTrack: "components/organisms/TimelineTrack/TimelineTrack.vue",
|
|
65
65
|
NexxtToaster: "components/organisms/Toaster/Toaster.vue",
|
|
66
|
-
NexxtVideoPlayer: "components/organisms/VideoPlayer/VideoPlayer.vue"
|
|
66
|
+
NexxtVideoPlayer: "components/organisms/VideoPlayer/VideoPlayer.vue",
|
|
67
|
+
NexxtEditorSettingsBlock: "components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue",
|
|
68
|
+
NexxtEditorFlexDirection: "components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue"
|
|
67
69
|
}, c = ["@nexxtmove/ui/ui.css", "@nexxtmove/ui/dist/ui.css"], l = (e, t) => e.some((e) => e === t || c.includes(e)), u = i({
|
|
68
70
|
meta: {
|
|
69
71
|
name: "@nexxtmove/ui",
|
|
@@ -85,8 +87,8 @@ var s = {
|
|
|
85
87
|
});
|
|
86
88
|
let d = u("./assets");
|
|
87
89
|
if (a(d)) {
|
|
88
|
-
let e = `/${[c.options.app.buildAssetsDir, "assets"].join("/").replace(/\/+/g, "/").replace(/^\/|\/$/g, "")}
|
|
89
|
-
|
|
90
|
+
let e = `/${[c.options.app.buildAssetsDir, "assets"].join("/").replace(/\/+/g, "/").replace(/^\/|\/$/g, "")}/`, t = c.options;
|
|
91
|
+
t.nitro.publicAssets ??= [], t.nitro.publicAssets.push({
|
|
90
92
|
dir: d,
|
|
91
93
|
baseURL: e,
|
|
92
94
|
maxAge: 31536e3
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nexxtmove/ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.16.0",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"@eslint/js": "^10.0.1",
|
|
38
38
|
"@nuxt/kit": "^4.5.2",
|
|
39
39
|
"@nuxt/schema": "^4.5.2",
|
|
40
|
-
"@storybook/addon-a11y": "^10.
|
|
40
|
+
"@storybook/addon-a11y": "^10.6.0",
|
|
41
41
|
"@storybook/addon-designs": "^11.1.4",
|
|
42
|
-
"@storybook/addon-docs": "^10.
|
|
43
|
-
"@storybook/addon-vitest": "^10.
|
|
44
|
-
"@storybook/builder-vite": "^10.
|
|
45
|
-
"@storybook/vue3-vite": "^10.
|
|
42
|
+
"@storybook/addon-docs": "^10.6.0",
|
|
43
|
+
"@storybook/addon-vitest": "^10.6.0",
|
|
44
|
+
"@storybook/builder-vite": "^10.6.0",
|
|
45
|
+
"@storybook/vue3-vite": "^10.6.0",
|
|
46
46
|
"@tailwindcss/vite": "^4.3.3",
|
|
47
47
|
"@types/node": "^26.2.0",
|
|
48
48
|
"@types/react": "^19.2.18",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"eslint-config-prettier": "^10.1.8",
|
|
60
60
|
"eslint-plugin-better-tailwindcss": "4.7.0",
|
|
61
61
|
"eslint-plugin-prettier": "^5.5.6",
|
|
62
|
-
"eslint-plugin-storybook": "10.
|
|
62
|
+
"eslint-plugin-storybook": "10.6.0",
|
|
63
63
|
"eslint-plugin-vue": "^10.10.0",
|
|
64
64
|
"flag-icons": "^7.5.0",
|
|
65
65
|
"globals": "^17.11.0",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"react": "^19.2.8",
|
|
71
71
|
"react-dom": "^19.2.8",
|
|
72
72
|
"remark-frontmatter": "^5.0.0",
|
|
73
|
-
"storybook": "^10.
|
|
73
|
+
"storybook": "^10.6.0",
|
|
74
74
|
"typescript-eslint": "^8.67.0",
|
|
75
75
|
"vite": "^8.2.1",
|
|
76
76
|
"vite-plugin-dts": "^5.0.3",
|
|
@@ -61,11 +61,18 @@ const iconSizeClasses: Record<SwitchSize, string> = {
|
|
|
61
61
|
<template>
|
|
62
62
|
<label class="inline-flex cursor-pointer items-center gap-2">
|
|
63
63
|
<slot v-if="labelPosition === 'before'" />
|
|
64
|
-
|
|
64
|
+
<!--
|
|
65
|
+
`shrink-0`: the track has a fixed pixel size, so letting flex shrink it
|
|
66
|
+
squashes the toggle the moment a sibling label wraps onto a second line.
|
|
67
|
+
-->
|
|
68
|
+
<span :class="['relative inline-block shrink-0', trackClasses[size]]">
|
|
65
69
|
<input v-bind="$attrs" type="checkbox" class="peer sr-only" v-model="model" />
|
|
66
70
|
<span
|
|
67
71
|
:class="[
|
|
68
72
|
'absolute inset-0 overflow-hidden rounded-[30px] border transition-colors duration-200',
|
|
73
|
+
// The input is `sr-only`, so the track has to render the focus ring.
|
|
74
|
+
// `outline` draws outside the box and is not clipped by `overflow-hidden`.
|
|
75
|
+
'peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-cornflower-blue-500',
|
|
69
76
|
model ? checkedColorClasses[color] : 'border-gray-500 bg-gray-200',
|
|
70
77
|
]"
|
|
71
78
|
>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import Switch from '../../../atoms/Switch/Switch.vue'
|
|
4
|
+
|
|
5
|
+
interface NexxtEditorSettingsBlockProps {
|
|
6
|
+
/** Header text of the block. Wraps over multiple lines when it is too long. */
|
|
7
|
+
label: string
|
|
8
|
+
/**
|
|
9
|
+
* Render a switch next to the label that collapses and expands the content.
|
|
10
|
+
* When `false` the content is always visible and the model is ignored.
|
|
11
|
+
*/
|
|
12
|
+
switchable?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
defineOptions({ name: 'NexxtEditorSettingsBlock' })
|
|
16
|
+
|
|
17
|
+
const { label, switchable = false } = defineProps<NexxtEditorSettingsBlockProps>()
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Open state of the block, driven by the switch. Only has an effect when
|
|
21
|
+
* `switchable` is `true`; the parent owns the state.
|
|
22
|
+
*/
|
|
23
|
+
const model = defineModel<boolean>({ default: true })
|
|
24
|
+
|
|
25
|
+
const open = computed(() => !switchable || model.value)
|
|
26
|
+
|
|
27
|
+
// Vue only drops an attribute on `false` for a fixed list of boolean
|
|
28
|
+
// attributes, and `inert` is not on that list: `:inert="false"` renders
|
|
29
|
+
// `inert="false"`, which a browser still treats as inert. `undefined` is the
|
|
30
|
+
// only value that removes the attribute again.
|
|
31
|
+
const inert = computed(() => (open.value ? undefined : true))
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<div class="border-b border-gray-200 py-4 last:border-b-0">
|
|
36
|
+
<!--
|
|
37
|
+
Switch.vue sets `inheritAttrs: false` and binds `$attrs` on its sr-only
|
|
38
|
+
input, so a class on <Switch> never reaches its root <label>. The child
|
|
39
|
+
variant below styles that label from the header instead, which keeps the
|
|
40
|
+
whole row clickable and the accessible name on the real <label>. The gap
|
|
41
|
+
has to go on that label too: the header has a single child in both modes,
|
|
42
|
+
so its own `gap` would never apply and the spacing would silently fall
|
|
43
|
+
back to the `gap-2` that Switch.vue sets for itself.
|
|
44
|
+
-->
|
|
45
|
+
<div class="flex items-center [&>label]:flex [&>label]:w-full [&>label]:gap-3">
|
|
46
|
+
<Switch v-if="switchable" v-model="model" size="sm" color="blue" label-position="before">
|
|
47
|
+
<span class="grow text-left small-normal text-gray-900">{{ label }}</span>
|
|
48
|
+
</Switch>
|
|
49
|
+
<p v-else class="small-normal text-gray-900">{{ label }}</p>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div
|
|
53
|
+
v-if="$slots.default"
|
|
54
|
+
:inert="inert"
|
|
55
|
+
:class="[
|
|
56
|
+
'grid',
|
|
57
|
+
open ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',
|
|
58
|
+
switchable &&
|
|
59
|
+
'transition-[grid-template-rows] duration-300 ease-in-out motion-reduce:transition-none',
|
|
60
|
+
]"
|
|
61
|
+
>
|
|
62
|
+
<!--
|
|
63
|
+
`overflow-hidden` is what makes the 0fr collapse clip, but it also clips
|
|
64
|
+
a focus ring on a full-width control in the slot, and the block has no
|
|
65
|
+
horizontal padding of its own. `-mx-1` widens the clipping box by 4px on
|
|
66
|
+
each side and the `px-1` below pushes the content back, so the ring has
|
|
67
|
+
room while the content keeps the same x position as the label.
|
|
68
|
+
-->
|
|
69
|
+
<div
|
|
70
|
+
:class="[
|
|
71
|
+
'-mx-1 min-h-0 overflow-hidden',
|
|
72
|
+
open ? 'opacity-100' : 'opacity-0',
|
|
73
|
+
switchable && 'transition-opacity duration-200 ease-in-out motion-reduce:transition-none',
|
|
74
|
+
]"
|
|
75
|
+
>
|
|
76
|
+
<!-- Padding sits on the inner element so nothing is left over at 0fr. -->
|
|
77
|
+
<div class="px-1 pt-1.5 pb-1">
|
|
78
|
+
<slot />
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</template>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* The flex direction as the editor needs it: the Tailwind class itself, so the
|
|
4
|
+
* consumer can put the model value straight on the element it styles.
|
|
5
|
+
*/
|
|
6
|
+
export type EditorFlexDirectionValue = 'flex-row' | 'flex-col'
|
|
7
|
+
|
|
8
|
+
/** Overridable copy for the two options. Every key is optional. */
|
|
9
|
+
export interface EditorFlexDirectionMessages {
|
|
10
|
+
/** Label of the `flex-row` option. Defaults to `'Horizontaal'`. */
|
|
11
|
+
horizontal?: string
|
|
12
|
+
/** Label of the `flex-col` option. Defaults to `'Verticaal'`. */
|
|
13
|
+
vertical?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface NexxtEditorFlexDirectionProps {
|
|
17
|
+
/**
|
|
18
|
+
* Header text of the settings block. Defaults to the Dutch `'Richting'`;
|
|
19
|
+
* the library has no i18n layer, so a consumer in another language passes
|
|
20
|
+
* its own copy in.
|
|
21
|
+
*/
|
|
22
|
+
label?: string
|
|
23
|
+
/**
|
|
24
|
+
* Labels of the two options. Defaults are Dutch and are merged per key, so
|
|
25
|
+
* overriding one label keeps the default of the other. Copy is never
|
|
26
|
+
* translated inside the component.
|
|
27
|
+
*/
|
|
28
|
+
messages?: EditorFlexDirectionMessages
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const DEFAULT_MESSAGES = {
|
|
32
|
+
horizontal: 'Horizontaal',
|
|
33
|
+
vertical: 'Verticaal',
|
|
34
|
+
} satisfies Required<EditorFlexDirectionMessages>
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<script lang="ts" setup>
|
|
38
|
+
import { computed } from 'vue'
|
|
39
|
+
import NexxtEditorSettingsBlock from '../../atoms/EditorSettingsBlock/EditorSettingsBlock.vue'
|
|
40
|
+
import NexxtToggleGroup from '../../../molecules/ToggleGroup/ToggleGroup.vue'
|
|
41
|
+
import type { NexxtToggleGroupOption } from '../../../molecules/ToggleGroup/ToggleGroup.vue'
|
|
42
|
+
|
|
43
|
+
defineOptions({ name: 'NexxtEditorFlexDirection' })
|
|
44
|
+
|
|
45
|
+
const { label = 'Richting', messages } = defineProps<NexxtEditorFlexDirectionProps>()
|
|
46
|
+
|
|
47
|
+
/** The selected direction, as the Tailwind class to apply. */
|
|
48
|
+
const model = defineModel<EditorFlexDirectionValue>({ required: true })
|
|
49
|
+
|
|
50
|
+
const copy = computed(() => ({ ...DEFAULT_MESSAGES, ...messages }))
|
|
51
|
+
|
|
52
|
+
const options = computed<NexxtToggleGroupOption[]>(() => [
|
|
53
|
+
{ value: 'flex-row', label: copy.value.horizontal, icon: 'arrow-right' },
|
|
54
|
+
{ value: 'flex-col', label: copy.value.vertical, icon: 'arrow-down' },
|
|
55
|
+
])
|
|
56
|
+
|
|
57
|
+
// ToggleGroup types its model as the open `string` of its options, so writing
|
|
58
|
+
// straight back into the narrower model is a type error. The setter is the one
|
|
59
|
+
// place that narrowing happens, and it is safe: the only values ToggleGroup can
|
|
60
|
+
// emit are the option values built above.
|
|
61
|
+
const selected = computed({
|
|
62
|
+
get: () => model.value,
|
|
63
|
+
set: (value: string) => {
|
|
64
|
+
model.value = value as EditorFlexDirectionValue
|
|
65
|
+
},
|
|
66
|
+
})
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<template>
|
|
70
|
+
<NexxtEditorSettingsBlock :label="label">
|
|
71
|
+
<NexxtToggleGroup v-model="selected" :options="options" />
|
|
72
|
+
</NexxtEditorSettingsBlock>
|
|
73
|
+
</template>
|
package/src/components.json
CHANGED
|
@@ -60,5 +60,7 @@
|
|
|
60
60
|
"NexxtTimelinePhaseblock": "components/organisms/TimelinePhaseblock/TimelinePhaseblock.vue",
|
|
61
61
|
"NexxtTimelineTrack": "components/organisms/TimelineTrack/TimelineTrack.vue",
|
|
62
62
|
"NexxtToaster": "components/organisms/Toaster/Toaster.vue",
|
|
63
|
-
"NexxtVideoPlayer": "components/organisms/VideoPlayer/VideoPlayer.vue"
|
|
63
|
+
"NexxtVideoPlayer": "components/organisms/VideoPlayer/VideoPlayer.vue",
|
|
64
|
+
"NexxtEditorSettingsBlock": "components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue",
|
|
65
|
+
"NexxtEditorFlexDirection": "components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue"
|
|
64
66
|
}
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,10 @@ export type { EnergyLabelLetter } from './components/atoms/EnergyLabel/EnergyLab
|
|
|
13
13
|
export type { IconType, NexxtIconName } from './components/atoms/Icon/Icon.vue'
|
|
14
14
|
export type { CustomIconName } from './components/atoms/Icon/customIcons'
|
|
15
15
|
export type { NexxtTabItem } from './components/molecules/Tabs/Tabs.vue'
|
|
16
|
+
export type {
|
|
17
|
+
EditorFlexDirectionMessages,
|
|
18
|
+
EditorFlexDirectionValue,
|
|
19
|
+
} from './components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue'
|
|
16
20
|
export type {
|
|
17
21
|
NexxtTemplateCardContentFeature,
|
|
18
22
|
NexxtTemplateCardProps,
|
|
@@ -36,6 +40,8 @@ export { default as NexxtCustomerJourneyTile } from './components/molecules/Cust
|
|
|
36
40
|
export { default as NexxtDatePicker } from './components/organisms/DatePicker/DatePicker.vue'
|
|
37
41
|
export { default as NexxtDoughnutChart } from './components/molecules/DoughnutChart/DoughnutChart.vue'
|
|
38
42
|
export { default as NexxtDropdownButton } from './components/organisms/DropdownButton/DropdownButton.vue'
|
|
43
|
+
export { default as NexxtEditorFlexDirection } from './components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue'
|
|
44
|
+
export { default as NexxtEditorSettingsBlock } from './components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue'
|
|
39
45
|
export { default as NexxtEnergyLabel } from './components/atoms/EnergyLabel/EnergyLabel.vue'
|
|
40
46
|
export { default as NexxtFloatingPanel } from './components/atoms/FloatingPanel/FloatingPanel.vue'
|
|
41
47
|
export { default as NexxtHeader } from './components/organisms/Header/Header.vue'
|
package/src/nuxt.ts
CHANGED
|
@@ -92,8 +92,21 @@ const module: NuxtModule<ModuleOptions> = defineNuxtModule<ModuleOptions>({
|
|
|
92
92
|
.replace(/\/+/g, '/')
|
|
93
93
|
.replace(/^\/|\/$/g, '')}/`
|
|
94
94
|
|
|
95
|
-
nuxt.
|
|
96
|
-
nuxt
|
|
95
|
+
// @nuxt/schema 4.x no longer declares `nitro` on NuxtOptions; the typing
|
|
96
|
+
// arrives through module augmentation in @nuxt/nitro-server, which ships
|
|
97
|
+
// with `nuxt` itself. This package depends on @nuxt/kit and @nuxt/schema
|
|
98
|
+
// only — deliberately, to stay free of app coupling — so the augmentation
|
|
99
|
+
// is absent here and the property has to be described locally. At runtime
|
|
100
|
+
// in a consumer the object is always present. Intersecting rather than
|
|
101
|
+
// replacing keeps this compatible with an installation that does have the
|
|
102
|
+
// augmentation: `options` stays the same object, so the mutation below
|
|
103
|
+
// still targets `nuxt.options.nitro`.
|
|
104
|
+
const options = nuxt.options as typeof nuxt.options & {
|
|
105
|
+
nitro: { publicAssets?: { dir: string; baseURL?: string; maxAge?: number }[] }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
options.nitro.publicAssets ??= []
|
|
109
|
+
options.nitro.publicAssets.push({
|
|
97
110
|
dir: assetsDir,
|
|
98
111
|
baseURL,
|
|
99
112
|
// Content-hashed filenames, so they are safe to cache indefinitely.
|