@nexxtmove/ui 1.28.0 → 1.30.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/nuxt.js CHANGED
@@ -70,12 +70,14 @@ var s = {
70
70
  NexxtVideoPlayer: "components/organisms/VideoPlayer/VideoPlayer.vue",
71
71
  NexxtEditorSettingsBlock: "components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue",
72
72
  NexxtEditorAlignItems: "components/editor/molecules/EditorAlignItems/EditorAlignItems.vue",
73
+ NexxtEditorBackgroundSize: "components/editor/molecules/EditorBackgroundSize/EditorBackgroundSize.vue",
73
74
  NexxtEditorBorder: "components/editor/molecules/EditorBorder/EditorBorder.vue",
74
75
  NexxtEditorColor: "components/editor/molecules/EditorColor/EditorColor.vue",
75
76
  NexxtEditorFlexDirection: "components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue",
76
77
  NexxtEditorGap: "components/editor/molecules/EditorGap/EditorGap.vue",
77
78
  NexxtEditorHeadingType: "components/editor/molecules/EditorHeadingType/EditorHeadingType.vue",
78
79
  NexxtEditorJustifyContent: "components/editor/molecules/EditorJustifyContent/EditorJustifyContent.vue",
80
+ NexxtEditorMaxWidth: "components/editor/molecules/EditorMaxWidth/EditorMaxWidth.vue",
79
81
  NexxtEditorPadding: "components/editor/molecules/EditorPadding/EditorPadding.vue",
80
82
  NexxtEditorRadius: "components/editor/molecules/EditorRadius/EditorRadius.vue",
81
83
  NexxtEditorTextAlign: "components/editor/molecules/EditorTextAlign/EditorTextAlign.vue"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nexxtmove/ui",
3
3
  "type": "module",
4
- "version": "1.28.0",
4
+ "version": "1.30.0",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",
@@ -66,7 +66,12 @@ const iconSizeClasses: Record<SwitchSize, string> = {
66
66
  squashes the toggle the moment a sibling label wraps onto a second line.
67
67
  -->
68
68
  <span :class="['relative inline-block shrink-0', trackClasses[size]]">
69
- <input v-bind="$attrs" type="checkbox" class="peer sr-only" v-model="model" />
69
+ <!--
70
+ `role="switch"` on a native checkbox: it is on/off rather than
71
+ selected/unselected, and the checked state is still the input's own, so
72
+ no `aria-checked` is set -- the browser derives it from the checkbox.
73
+ -->
74
+ <input v-bind="$attrs" type="checkbox" role="switch" class="peer sr-only" v-model="model" />
70
75
  <span
71
76
  :class="[
72
77
  'absolute inset-0 overflow-hidden rounded-[30px] border transition-colors duration-200',
@@ -0,0 +1,83 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The background size 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 EditorBackgroundSizeValue = 'bg-cover' | 'bg-contain' | 'bg-auto'
7
+
8
+ /** Overridable copy for the three options. Every key is optional. */
9
+ export interface EditorBackgroundSizeMessages {
10
+ /** Accessible name of the `bg-cover` option. Defaults to `'Opvullen'`. */
11
+ cover?: string
12
+ /** Accessible name of the `bg-contain` option. Defaults to `'Passend'`. */
13
+ contain?: string
14
+ /** Accessible name of the `bg-auto` option. Defaults to `'Origineel'`. */
15
+ auto?: string
16
+ }
17
+
18
+ export interface NexxtEditorBackgroundSizeProps {
19
+ /**
20
+ * Header text of the settings block. Defaults to the Dutch `'Vulling'`;
21
+ * the library has no i18n layer, so a consumer in another language passes
22
+ * its own copy in.
23
+ */
24
+ label?: string
25
+ /**
26
+ * Copy of the three options. The options are icon-only and show no tooltip,
27
+ * so this copy is purely the accessible name of each button. Defaults are
28
+ * Dutch and are merged per key, so overriding one keeps the defaults of the
29
+ * others. Copy is never translated inside the component.
30
+ */
31
+ messages?: EditorBackgroundSizeMessages
32
+ }
33
+
34
+ const DEFAULT_MESSAGES = {
35
+ cover: 'Opvullen',
36
+ contain: 'Passend',
37
+ auto: 'Origineel',
38
+ } satisfies Required<EditorBackgroundSizeMessages>
39
+ </script>
40
+
41
+ <script lang="ts" setup>
42
+ import { computed } from 'vue'
43
+ import NexxtEditorSettingsBlock from '../../atoms/EditorSettingsBlock/EditorSettingsBlock.vue'
44
+ import NexxtToggleGroup from '../../../molecules/ToggleGroup/ToggleGroup.vue'
45
+ import type { NexxtToggleGroupOption } from '../../../molecules/ToggleGroup/ToggleGroup.vue'
46
+
47
+ defineOptions({ name: 'NexxtEditorBackgroundSize' })
48
+
49
+ const { label = 'Vulling', messages } = defineProps<NexxtEditorBackgroundSizeProps>()
50
+
51
+ /** The selected background size, as the Tailwind class to apply. */
52
+ const model = defineModel<EditorBackgroundSizeValue>({ required: true })
53
+
54
+ const copy = computed(() => ({ ...DEFAULT_MESSAGES, ...messages }))
55
+
56
+ // Icon-only and deliberately without tooltips, matching the other editor
57
+ // molecules in the panel (align items, justify content, text align): labelled
58
+ // options do not fit the width the editor sidebar gives this block. The copy
59
+ // travels as `ariaLabel`, so the buttons still have a name for assistive
60
+ // technology.
61
+ const options = computed<NexxtToggleGroupOption[]>(() => [
62
+ { value: 'bg-cover', icon: 'arrows-maximize', ariaLabel: copy.value.cover },
63
+ { value: 'bg-contain', icon: 'arrows-minimize', ariaLabel: copy.value.contain },
64
+ { value: 'bg-auto', icon: 'image', ariaLabel: copy.value.auto },
65
+ ])
66
+
67
+ // ToggleGroup types its model as the open `string` of its options, so writing
68
+ // straight back into the narrower model is a type error. The setter is the one
69
+ // place that narrowing happens, and it is safe: the only values ToggleGroup can
70
+ // emit are the option values built above.
71
+ const selected = computed({
72
+ get: () => model.value,
73
+ set: (value: string) => {
74
+ model.value = value as EditorBackgroundSizeValue
75
+ },
76
+ })
77
+ </script>
78
+
79
+ <template>
80
+ <NexxtEditorSettingsBlock :label="label">
81
+ <NexxtToggleGroup v-model="selected" :options="options" />
82
+ </NexxtEditorSettingsBlock>
83
+ </template>
@@ -0,0 +1,146 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The steps the slider can land on: the `max-w-*` sizes, with the px numbers
4
+ * mirroring their values (rem × 16). These are Tailwind's own container sizes,
5
+ * not Figma tokens -- `tailwind/` defines no `--container-*`, so the token sync
6
+ * cannot move them. The desync to watch for is a Tailwind major that renames or
7
+ * renumbers the scale: nothing here fails when that happens, the numbers just
8
+ * stop matching the CSS, so this list has to be checked by hand on an upgrade.
9
+ */
10
+ export const EDITOR_MAX_WIDTH_STEPS = [
11
+ { token: 'xs', px: 320 },
12
+ { token: 'sm', px: 384 },
13
+ { token: 'md', px: 448 },
14
+ { token: 'lg', px: 512 },
15
+ { token: 'xl', px: 576 },
16
+ { token: '2xl', px: 672 },
17
+ { token: '3xl', px: 768 },
18
+ { token: '4xl', px: 896 },
19
+ { token: '5xl', px: 1024 },
20
+ { token: '6xl', px: 1152 },
21
+ { token: '7xl', px: 1280 },
22
+ ] as const
23
+
24
+ /**
25
+ * The maximum width as the editor needs it: the Tailwind class itself, so the
26
+ * consumer can put the model value straight on the element it styles.
27
+ */
28
+ export type EditorMaxWidthValue = `max-w-${(typeof EDITOR_MAX_WIDTH_STEPS)[number]['token']}`
29
+
30
+ /** Overridable copy of the value readout. Every key is optional. */
31
+ export interface EditorMaxWidthMessages {
32
+ /**
33
+ * Unit shown behind the value. Defaults to `'px'`. Keep it to a short symbol
34
+ * such as `'px'` or `'pt'`: the readout is only as wide as `1280 px` needs,
35
+ * and a spelled-out unit grows it and pushes the slider in.
36
+ */
37
+ unit?: string
38
+ }
39
+
40
+ export interface NexxtEditorMaxWidthProps {
41
+ /**
42
+ * Header text of the settings block. Defaults to the Dutch
43
+ * `'Vaste breedte'` -- switched off the page runs full width, so the setting
44
+ * is the fixed width, not a maximum. The library has no i18n layer, so a
45
+ * consumer in another language passes its own copy in.
46
+ */
47
+ label?: string
48
+ /**
49
+ * Copy of the value readout. Merged per key, so overriding one key keeps the
50
+ * defaults of the others. Copy is never translated inside the component.
51
+ */
52
+ messages?: EditorMaxWidthMessages
53
+ }
54
+
55
+ const DEFAULT_MESSAGES = {
56
+ unit: 'px',
57
+ } satisfies Required<EditorMaxWidthMessages>
58
+ </script>
59
+
60
+ <script lang="ts" setup>
61
+ import { computed } from 'vue'
62
+ import NexxtEditorSettingsBlock from '../../atoms/EditorSettingsBlock/EditorSettingsBlock.vue'
63
+ import NexxtSlider from '../../../atoms/Slider/Slider.vue'
64
+
65
+ defineOptions({ name: 'NexxtEditorMaxWidth' })
66
+
67
+ const { label = 'Vaste breedte', messages } = defineProps<NexxtEditorMaxWidthProps>()
68
+
69
+ /** The selected maximum width, as the Tailwind class to apply. */
70
+ const model = defineModel<EditorMaxWidthValue>({ required: true })
71
+
72
+ /**
73
+ * Open state of the block. Switched off means the page runs full width, which
74
+ * is the absence of a class rather than a value of its own: the consumer simply
75
+ * writes no `max-w-*` then. The chosen width is kept while the block is
76
+ * collapsed, so switching back on restores it.
77
+ */
78
+ const enabled = defineModel<boolean>('enabled', { default: true })
79
+
80
+ const copy = computed(() => ({ ...DEFAULT_MESSAGES, ...messages }))
81
+
82
+ const maxIndex = EDITOR_MAX_WIDTH_STEPS.length - 1
83
+
84
+ /**
85
+ * Position of the current value on the step list. A value that is not on the
86
+ * list -- a stored `max-w-prose` from before this component, say -- falls back
87
+ * to the first step instead of leaving the thumb off the track; the first
88
+ * change writes a valid class back.
89
+ */
90
+ const stepIndex = computed(() =>
91
+ Math.max(
92
+ 0,
93
+ EDITOR_MAX_WIDTH_STEPS.findIndex(({ token }) => `max-w-${token}` === model.value),
94
+ ),
95
+ )
96
+
97
+ // The slider moves over the index, not over the px value, so its model is
98
+ // translated both ways here.
99
+ const sliderValue = computed({
100
+ get: () => [stepIndex.value],
101
+ set: ([index]) => {
102
+ model.value = `max-w-${EDITOR_MAX_WIDTH_STEPS[index].token}`
103
+ },
104
+ })
105
+
106
+ const displayValue = computed(
107
+ () => `${EDITOR_MAX_WIDTH_STEPS[stepIndex.value].px} ${copy.value.unit}`,
108
+ )
109
+ </script>
110
+
111
+ <template>
112
+ <NexxtEditorSettingsBlock v-model="enabled" :label="label" switchable>
113
+ <div class="flex items-center gap-4">
114
+ <!--
115
+ Slider's own `showValue` prints its model, which here is the step index
116
+ rather than the width, so the readout is rendered next to it instead.
117
+ The thumb has the same problem in `aria-valuenow`, which
118
+ `aria-valuetext` overrides with the string the readout shows. The block
119
+ label is the switch's own label, not a <label> for the slider, so the
120
+ name goes on the thumb explicitly.
121
+ -->
122
+ <NexxtSlider
123
+ v-model="sliderValue"
124
+ :min="0"
125
+ :max="maxIndex"
126
+ :step="1"
127
+ :aria-label="label"
128
+ :aria-valuetext="displayValue"
129
+ />
130
+
131
+ <!--
132
+ `min-w-16` rather than the `min-w-12` of the narrower editor sliders:
133
+ `1280 px` does not fit in 12. That plus `shrink-0` is what fixes the
134
+ width of the box, so the slider keeps its size while dragging;
135
+ `tabular-nums` only stops the digits from jittering inside it.
136
+ gray-700, not the gray-500 Slider uses for its own readout: axe puts
137
+ gray-500 on white at 1.84:1, well under the 4.5:1 it needs at this size.
138
+ -->
139
+ <span
140
+ class="min-w-16 shrink-0 text-right small-normal whitespace-nowrap text-gray-700 tabular-nums"
141
+ >
142
+ {{ displayValue }}
143
+ </span>
144
+ </div>
145
+ </NexxtEditorSettingsBlock>
146
+ </template>
@@ -67,12 +67,14 @@
67
67
  "NexxtVideoPlayer": "components/organisms/VideoPlayer/VideoPlayer.vue",
68
68
  "NexxtEditorSettingsBlock": "components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue",
69
69
  "NexxtEditorAlignItems": "components/editor/molecules/EditorAlignItems/EditorAlignItems.vue",
70
+ "NexxtEditorBackgroundSize": "components/editor/molecules/EditorBackgroundSize/EditorBackgroundSize.vue",
70
71
  "NexxtEditorBorder": "components/editor/molecules/EditorBorder/EditorBorder.vue",
71
72
  "NexxtEditorColor": "components/editor/molecules/EditorColor/EditorColor.vue",
72
73
  "NexxtEditorFlexDirection": "components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue",
73
74
  "NexxtEditorGap": "components/editor/molecules/EditorGap/EditorGap.vue",
74
75
  "NexxtEditorHeadingType": "components/editor/molecules/EditorHeadingType/EditorHeadingType.vue",
75
76
  "NexxtEditorJustifyContent": "components/editor/molecules/EditorJustifyContent/EditorJustifyContent.vue",
77
+ "NexxtEditorMaxWidth": "components/editor/molecules/EditorMaxWidth/EditorMaxWidth.vue",
76
78
  "NexxtEditorPadding": "components/editor/molecules/EditorPadding/EditorPadding.vue",
77
79
  "NexxtEditorRadius": "components/editor/molecules/EditorRadius/EditorRadius.vue",
78
80
  "NexxtEditorTextAlign": "components/editor/molecules/EditorTextAlign/EditorTextAlign.vue"
package/src/index.ts CHANGED
@@ -23,6 +23,10 @@ export type {
23
23
  EditorAlignItemsMessages,
24
24
  EditorAlignItemsValue,
25
25
  } from './components/editor/molecules/EditorAlignItems/EditorAlignItems.vue'
26
+ export type {
27
+ EditorBackgroundSizeMessages,
28
+ EditorBackgroundSizeValue,
29
+ } from './components/editor/molecules/EditorBackgroundSize/EditorBackgroundSize.vue'
26
30
  export type {
27
31
  EditorFlexDirectionMessages,
28
32
  EditorFlexDirectionValue,
@@ -56,6 +60,11 @@ export type {
56
60
  EditorJustifyContentMessages,
57
61
  EditorJustifyContentValue,
58
62
  } from './components/editor/molecules/EditorJustifyContent/EditorJustifyContent.vue'
63
+ export { EDITOR_MAX_WIDTH_STEPS } from './components/editor/molecules/EditorMaxWidth/EditorMaxWidth.vue'
64
+ export type {
65
+ EditorMaxWidthMessages,
66
+ EditorMaxWidthValue,
67
+ } from './components/editor/molecules/EditorMaxWidth/EditorMaxWidth.vue'
59
68
  export type { EditorPaddingMessages } from './components/editor/molecules/EditorPadding/EditorPadding.vue'
60
69
  export type {
61
70
  NexxtTemplateCardContentFeature,
@@ -81,12 +90,14 @@ export { default as NexxtDatePicker } from './components/organisms/DatePicker/Da
81
90
  export { default as NexxtDoughnutChart } from './components/molecules/DoughnutChart/DoughnutChart.vue'
82
91
  export { default as NexxtDropdownButton } from './components/organisms/DropdownButton/DropdownButton.vue'
83
92
  export { default as NexxtEditorAlignItems } from './components/editor/molecules/EditorAlignItems/EditorAlignItems.vue'
93
+ export { default as NexxtEditorBackgroundSize } from './components/editor/molecules/EditorBackgroundSize/EditorBackgroundSize.vue'
84
94
  export { default as NexxtEditorBorder } from './components/editor/molecules/EditorBorder/EditorBorder.vue'
85
95
  export { default as NexxtEditorColor } from './components/editor/molecules/EditorColor/EditorColor.vue'
86
96
  export { default as NexxtEditorFlexDirection } from './components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue'
87
97
  export { default as NexxtEditorGap } from './components/editor/molecules/EditorGap/EditorGap.vue'
88
98
  export { default as NexxtEditorHeadingType } from './components/editor/molecules/EditorHeadingType/EditorHeadingType.vue'
89
99
  export { default as NexxtEditorJustifyContent } from './components/editor/molecules/EditorJustifyContent/EditorJustifyContent.vue'
100
+ export { default as NexxtEditorMaxWidth } from './components/editor/molecules/EditorMaxWidth/EditorMaxWidth.vue'
90
101
  export { default as NexxtEditorPadding } from './components/editor/molecules/EditorPadding/EditorPadding.vue'
91
102
  export { default as NexxtEditorRadius } from './components/editor/molecules/EditorRadius/EditorRadius.vue'
92
103
  export { default as NexxtEditorSettingsBlock } from './components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue'