@nexxtmove/ui 1.20.0 → 1.21.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
@@ -69,6 +69,7 @@ var s = {
69
69
  NexxtEditorFlexDirection: "components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue",
70
70
  NexxtEditorGap: "components/editor/molecules/EditorGap/EditorGap.vue",
71
71
  NexxtEditorJustifyContent: "components/editor/molecules/EditorJustifyContent/EditorJustifyContent.vue",
72
+ NexxtEditorRadius: "components/editor/molecules/EditorRadius/EditorRadius.vue",
72
73
  NexxtEditorPadding: "components/editor/molecules/EditorPadding/EditorPadding.vue"
73
74
  }, c = ["@nexxtmove/ui/ui.css", "@nexxtmove/ui/dist/ui.css"], l = (e, t) => e.some((e) => e === t || c.includes(e)), u = i({
74
75
  meta: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nexxtmove/ui",
3
3
  "type": "module",
4
- "version": "1.20.0",
4
+ "version": "1.21.0",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",
@@ -0,0 +1,137 @@
1
+ <script lang="ts">
2
+ /**
3
+ * The steps the slider can land on: the radius scale the library actually has,
4
+ * which is the Figma theme tokens plus the Tailwind defaults that sit on top of
5
+ * them -- the theme adds no `--radius-*: initial`, so `rounded-2xl` through
6
+ * `rounded-4xl` and `rounded-full` resolve to Tailwind's own values. The px
7
+ * numbers mirror those values (rem × 16). Known limitation: the theme file is
8
+ * overwritten wholesale by the Figma token sync, and a sync that changes a
9
+ * radius does not reach this list -- it has to be updated by hand.
10
+ *
11
+ * `full` is last and carries no px: it is a pill, not a size on the scale, so
12
+ * the readout names it instead of measuring it.
13
+ */
14
+ const RADIUS_STEPS = [
15
+ { token: 'none', px: 0 },
16
+ { token: 'xs', px: 2 },
17
+ { token: 'sm', px: 4 },
18
+ { token: 'md', px: 6 },
19
+ { token: 'lg', px: 8 },
20
+ { token: 'xl', px: 12 },
21
+ { token: '2xl', px: 16 },
22
+ { token: '3xl', px: 24 },
23
+ { token: '4xl', px: 32 },
24
+ { token: 'full', px: null },
25
+ ] as const
26
+
27
+ /**
28
+ * The radius as the editor needs it: the Tailwind class itself, so the consumer
29
+ * can put the model value straight on the element it styles.
30
+ */
31
+ export type EditorRadiusValue = `rounded-${(typeof RADIUS_STEPS)[number]['token']}`
32
+
33
+ /** Overridable copy of the value readout. Every key is optional. */
34
+ export interface EditorRadiusMessages {
35
+ /** Unit shown behind the value. Defaults to `'px'`. */
36
+ unit?: string
37
+ /**
38
+ * Readout of the last step, `rounded-full`, which has no px size. Defaults to
39
+ * the Dutch `'Rond'`.
40
+ */
41
+ full?: string
42
+ }
43
+
44
+ export interface NexxtEditorRadiusProps {
45
+ /**
46
+ * Header text of the settings block. Defaults to the Dutch
47
+ * `'Hoekafronding'`; the library has no i18n layer, so a consumer in another
48
+ * language passes its own copy in.
49
+ */
50
+ label?: string
51
+ /**
52
+ * Copy of the value readout. Merged per key, so overriding one key keeps the
53
+ * defaults of the others. Copy is never translated inside the component.
54
+ */
55
+ messages?: EditorRadiusMessages
56
+ }
57
+
58
+ const DEFAULT_MESSAGES = {
59
+ unit: 'px',
60
+ full: 'Rond',
61
+ } satisfies Required<EditorRadiusMessages>
62
+ </script>
63
+
64
+ <script lang="ts" setup>
65
+ import { computed } from 'vue'
66
+ import NexxtEditorSettingsBlock from '../../atoms/EditorSettingsBlock/EditorSettingsBlock.vue'
67
+ import NexxtSlider from '../../../atoms/Slider/Slider.vue'
68
+
69
+ defineOptions({ name: 'NexxtEditorRadius' })
70
+
71
+ const { label = 'Hoekafronding', messages } = defineProps<NexxtEditorRadiusProps>()
72
+
73
+ /** The selected radius, as the Tailwind class to apply. */
74
+ const model = defineModel<EditorRadiusValue>({ required: true })
75
+
76
+ const copy = computed(() => ({ ...DEFAULT_MESSAGES, ...messages }))
77
+
78
+ const maxIndex = RADIUS_STEPS.length - 1
79
+
80
+ /**
81
+ * Position of the current value on the step list. A value that is not on the
82
+ * list -- a stored `rounded-5xl` from before this component, say -- falls back
83
+ * to the first step instead of leaving the thumb off the track; the first
84
+ * change writes a valid class back.
85
+ */
86
+ const stepIndex = computed(() =>
87
+ Math.max(
88
+ 0,
89
+ RADIUS_STEPS.findIndex(({ token }) => `rounded-${token}` === model.value),
90
+ ),
91
+ )
92
+
93
+ // The slider moves over the index, not over the px value, so its model is
94
+ // translated both ways here.
95
+ const sliderValue = computed({
96
+ get: () => [stepIndex.value],
97
+ set: ([index]) => {
98
+ model.value = `rounded-${RADIUS_STEPS[index].token}`
99
+ },
100
+ })
101
+
102
+ const displayValue = computed(() => {
103
+ const { px } = RADIUS_STEPS[stepIndex.value]
104
+
105
+ return px === null ? copy.value.full : `${px} ${copy.value.unit}`
106
+ })
107
+ </script>
108
+
109
+ <template>
110
+ <NexxtEditorSettingsBlock :label="label">
111
+ <div class="flex items-center gap-4">
112
+ <!--
113
+ Slider's own `showValue` prints its model, which here is the step index
114
+ rather than the radius, so the readout is rendered next to it instead.
115
+ The thumb has the same problem in `aria-valuenow`, which
116
+ `aria-valuetext` overrides with the string the readout shows. The block
117
+ label is a <p>, not a <label>, so the name goes on the thumb explicitly.
118
+ -->
119
+ <NexxtSlider
120
+ v-model="sliderValue"
121
+ :min="0"
122
+ :max="maxIndex"
123
+ :step="1"
124
+ :aria-label="label"
125
+ :aria-valuetext="displayValue"
126
+ />
127
+
128
+ <!--
129
+ gray-700, not the gray-500 Slider uses for its own readout: axe puts
130
+ gray-500 on white at 1.84:1, well under the 4.5:1 it needs at this size.
131
+ -->
132
+ <span class="min-w-12 shrink-0 text-right small-normal whitespace-nowrap text-gray-700">
133
+ {{ displayValue }}
134
+ </span>
135
+ </div>
136
+ </NexxtEditorSettingsBlock>
137
+ </template>
@@ -66,5 +66,6 @@
66
66
  "NexxtEditorFlexDirection": "components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue",
67
67
  "NexxtEditorGap": "components/editor/molecules/EditorGap/EditorGap.vue",
68
68
  "NexxtEditorJustifyContent": "components/editor/molecules/EditorJustifyContent/EditorJustifyContent.vue",
69
+ "NexxtEditorRadius": "components/editor/molecules/EditorRadius/EditorRadius.vue",
69
70
  "NexxtEditorPadding": "components/editor/molecules/EditorPadding/EditorPadding.vue"
70
71
  }
package/src/index.ts CHANGED
@@ -25,6 +25,10 @@ export type {
25
25
  EditorGapMessages,
26
26
  EditorGapValue,
27
27
  } from './components/editor/molecules/EditorGap/EditorGap.vue'
28
+ export type {
29
+ EditorRadiusMessages,
30
+ EditorRadiusValue,
31
+ } from './components/editor/molecules/EditorRadius/EditorRadius.vue'
28
32
  export type {
29
33
  EditorJustifyContentMessages,
30
34
  EditorJustifyContentValue,
@@ -57,6 +61,7 @@ export { default as NexxtEditorAlignItems } from './components/editor/molecules/
57
61
  export { default as NexxtEditorFlexDirection } from './components/editor/molecules/EditorFlexDirection/EditorFlexDirection.vue'
58
62
  export { default as NexxtEditorGap } from './components/editor/molecules/EditorGap/EditorGap.vue'
59
63
  export { default as NexxtEditorJustifyContent } from './components/editor/molecules/EditorJustifyContent/EditorJustifyContent.vue'
64
+ export { default as NexxtEditorRadius } from './components/editor/molecules/EditorRadius/EditorRadius.vue'
60
65
  export { default as NexxtEditorPadding } from './components/editor/molecules/EditorPadding/EditorPadding.vue'
61
66
  export { default as NexxtEditorSettingsBlock } from './components/editor/atoms/EditorSettingsBlock/EditorSettingsBlock.vue'
62
67
  export { default as NexxtEnergyLabel } from './components/atoms/EnergyLabel/EnergyLabel.vue'