@nexxtmove/ui 2.0.0 → 2.1.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/molecules/EditorColor/EditorColor.vue.d.ts +10 -0
- package/dist/components/organisms/ColorPicker/ColorPicker.vue.d.ts +5 -0
- package/dist/index.js +559 -543
- package/package.json +1 -1
- package/src/components/editor/molecules/EditorColor/EditorColor.vue +35 -6
- package/src/components/organisms/ColorPicker/ColorPicker.vue +20 -2
package/package.json
CHANGED
|
@@ -83,6 +83,16 @@ export interface NexxtEditorColorProps {
|
|
|
83
83
|
* 8-digit hex is left out. Without roles the section is not rendered.
|
|
84
84
|
*/
|
|
85
85
|
themeRoles?: EditorColorThemeRole[]
|
|
86
|
+
/**
|
|
87
|
+
* Offer an opacity slider in the picker. A colour picked below full opacity is
|
|
88
|
+
* written as an 8-digit hex (`bg-[#1777ea80]`); a fully opaque one keeps the
|
|
89
|
+
* 6-digit form. The slider is hidden while a theme role is selected: a role
|
|
90
|
+
* class carries no opacity. Off by default, in which case a stored 8-digit hex
|
|
91
|
+
* is shown opaque and only replaced once a new colour is picked. Turning it off
|
|
92
|
+
* while a translucent colour is set does write at once: the picker drops the
|
|
93
|
+
* alpha and the model gets the opaque 6-digit hex.
|
|
94
|
+
*/
|
|
95
|
+
showAlpha?: boolean
|
|
86
96
|
}
|
|
87
97
|
|
|
88
98
|
const DEFAULT_MESSAGES = {
|
|
@@ -94,9 +104,9 @@ const DEFAULT_MESSAGES = {
|
|
|
94
104
|
/**
|
|
95
105
|
* A literal model value: one of the two prefixes, then a 6- or 8-digit hex between
|
|
96
106
|
* brackets. A `border-[…]` class is therefore read as unparseable, the same as
|
|
97
|
-
* any other class this component does not own. The
|
|
98
|
-
*
|
|
99
|
-
*
|
|
107
|
+
* any other class this component does not own. The alpha pair is accepted on
|
|
108
|
+
* read whether or not `showAlpha` is set, so a stored `#1777EA80` survives a
|
|
109
|
+
* round trip either way.
|
|
100
110
|
*/
|
|
101
111
|
const VALUE_PATTERN = /^(bg|text)-\[(#[0-9A-Fa-f]{6}(?:[0-9A-Fa-f]{2})?)\]$/
|
|
102
112
|
|
|
@@ -109,6 +119,12 @@ const ROLE_PATTERN = new RegExp(`^(?:bg|text)-theme-(${ROLES.join('|')})$`)
|
|
|
109
119
|
|
|
110
120
|
/** The picker throws on a colour it cannot read, so a role's hex is checked first. */
|
|
111
121
|
const ROLE_HEX_PATTERN = /^#[0-9A-Fa-f]{6}(?:[0-9A-Fa-f]{2})?$/
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The picker writes `#rrggbbaa` only below full opacity, but an alpha a hair
|
|
125
|
+
* under 1 still rounds to `ff`. That pair says nothing, so it is dropped.
|
|
126
|
+
*/
|
|
127
|
+
const OPAQUE_ALPHA_PATTERN = /^(#[0-9A-Fa-f]{6})[fF]{2}$/
|
|
112
128
|
</script>
|
|
113
129
|
|
|
114
130
|
<script lang="ts" setup>
|
|
@@ -126,6 +142,7 @@ const {
|
|
|
126
142
|
messages,
|
|
127
143
|
suggestions = [],
|
|
128
144
|
themeRoles = [],
|
|
145
|
+
showAlpha = false,
|
|
129
146
|
} = defineProps<NexxtEditorColorProps>()
|
|
130
147
|
|
|
131
148
|
/**
|
|
@@ -181,8 +198,19 @@ const activeRole = computed(() => offeredRoles.value.find(({ role }) => role ===
|
|
|
181
198
|
* reports nothing when it is told to pick the string it already has, so a role's
|
|
182
199
|
* hex is handed over in its 8-digit form: with `show-alpha` off the picker never
|
|
183
200
|
* reports an alpha pair, which makes every pick a change.
|
|
201
|
+
*
|
|
202
|
+
* A role has no opacity here, so an alpha pair in the role's own hex is replaced
|
|
203
|
+
* by `ff`. Handed over translucent, the picker would drop that alpha the moment
|
|
204
|
+
* the role turns `show-alpha` off, and write the opaque hex over the role.
|
|
205
|
+
*/
|
|
206
|
+
const pickerHex = (roleHex: string) => `${roleHex.slice(0, 7)}ff`
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* A role class has no opacity, so the slider is only offered for a literal.
|
|
210
|
+
* Hiding it is also what keeps the trick in `pickerHex` working: without the
|
|
211
|
+
* alpha channel the picker reads the role's hex as opaque.
|
|
184
212
|
*/
|
|
185
|
-
const
|
|
213
|
+
const alphaEnabled = computed(() => showAlpha && !activeRole.value)
|
|
186
214
|
|
|
187
215
|
// An unparseable value -- empty, a token class such as `bg-red-500`, or copy
|
|
188
216
|
// from before this component -- leaves the picker empty and its placeholder
|
|
@@ -195,7 +223,8 @@ const picked = computed({
|
|
|
195
223
|
// would still wipe a perfectly good colour, so it is dropped rather than
|
|
196
224
|
// written through. The picker keeps rendering the model's colour.
|
|
197
225
|
set: (value: string) => {
|
|
198
|
-
|
|
226
|
+
const color = value.replace(OPAQUE_ALPHA_PATTERN, '$1')
|
|
227
|
+
if (isHex(color)) model.value = `${property}-[${color}]`
|
|
199
228
|
},
|
|
200
229
|
})
|
|
201
230
|
|
|
@@ -234,7 +263,7 @@ watch(
|
|
|
234
263
|
full-width
|
|
235
264
|
match-width
|
|
236
265
|
:formats="['hex']"
|
|
237
|
-
:show-alpha="
|
|
266
|
+
:show-alpha="alphaEnabled"
|
|
238
267
|
:placeholder="copy.placeholder"
|
|
239
268
|
:suggestions="{ hex: suggestions }"
|
|
240
269
|
:suggestions-label="copy.suggestionsLabel"
|
|
@@ -27,6 +27,11 @@ export interface NexxtColorPickerProps {
|
|
|
27
27
|
error?: boolean
|
|
28
28
|
errorMessage?: string
|
|
29
29
|
required?: boolean
|
|
30
|
+
/**
|
|
31
|
+
* Offer an opacity slider and accept colours below full opacity. Turning it
|
|
32
|
+
* off while the colour is translucent writes the opaque colour to the model
|
|
33
|
+
* at once.
|
|
34
|
+
*/
|
|
30
35
|
showAlpha?: boolean
|
|
31
36
|
formats?: ColorFormat[]
|
|
32
37
|
fullWidth?: boolean
|
|
@@ -168,11 +173,24 @@ watch(
|
|
|
168
173
|
},
|
|
169
174
|
)
|
|
170
175
|
|
|
176
|
+
// A parent can swap the value in the same update that turns alpha off, and this
|
|
177
|
+
// watcher may run before the one above. So the colour is read from the model,
|
|
178
|
+
// which already holds the new value, not from `colorObj`, which may not.
|
|
179
|
+
const currentColor = () => {
|
|
180
|
+
if (!model.value) return colorObj.value
|
|
181
|
+
try {
|
|
182
|
+
return normalizeColor(model.value)
|
|
183
|
+
} catch {
|
|
184
|
+
return colorObj.value
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
171
188
|
watch(
|
|
172
189
|
() => props.showAlpha,
|
|
173
190
|
(showAlpha) => {
|
|
174
|
-
|
|
175
|
-
|
|
191
|
+
const current = currentColor()
|
|
192
|
+
if (!showAlpha && current.alpha < 1) {
|
|
193
|
+
const updated = withoutAlpha(current)
|
|
176
194
|
colorObj.value = updated
|
|
177
195
|
model.value = fmt(updated, activeFormat.value)
|
|
178
196
|
}
|