diff --git a/docs/_layouts/palette.njk b/docs/_layouts/palette.njk
index 0b74d7964..c275f0162 100644
--- a/docs/_layouts/palette.njk
+++ b/docs/_layouts/palette.njk
@@ -151,8 +151,9 @@
:model-value="computedGrayChroma"
@update:model-value="grayChroma = $event"
:default-color="baseCoreColors[computedGrayColor]"
- :default-value="baseCoreColors[originalGrayColor].oklch.c"
- :min="0" :max-relative="maxGrayChroma" :step="0.01"
+ :base-value="baseCoreColors[originalGrayColor].oklch.c"
+ :default-value-relative="originalGrayChroma"
+ :min="0" :max-relative="maxGrayChroma" :step="0.00001"
label="Gray colorfulness" label-min="Neutral" :label-max="moreHue[computedGrayColor]"
>
@@ -177,7 +178,7 @@
:default-value="seedColors[colorToIndex[hue].core].inputColor?.oklch.c"
coord="c"
:min="Math.max(coreColors.gray.oklch.c, ...Object.keys(seedHues[hue]).filter(t => t !== coreLevels[hue]).map(t => seedHues[hue][t].oklch.c))"
- :max="getMaxChroma(colors[hue].core?.oklch.l, colors[hue].core?.oklch.h) - 0.001" :step="0.001"
+ :max="getMaxChroma(colors[hue].core?.oklch.l, colors[hue].core?.oklch.h) - 0.001" :step="0.00001"
label="Adjust colorfulness" label-min="More muted" label-max="More vibrant"
label-default="Entered color"
format-type="scale"
diff --git a/docs/docs/palettes/app/vue-components/color-input.js b/docs/docs/palettes/app/vue-components/color-input.js
index 3e12fef95..95d7e0b68 100644
--- a/docs/docs/palettes/app/vue-components/color-input.js
+++ b/docs/docs/palettes/app/vue-components/color-input.js
@@ -11,10 +11,10 @@ const template = `
v-model:color="color" :default-value="inputLCH[2]" >
+ v-model:color="color" :default-value="inputLCH[1]" format-type="scale" :format-base-value="maxChroma" >
+ v-model:color="color" :default-value="inputLCH[0]" format-type="scale" :format-base-value="1" >
diff --git a/docs/docs/palettes/app/vue-components/color-slider.js b/docs/docs/palettes/app/vue-components/color-slider.js
index 1d1ebde18..446c143b5 100644
--- a/docs/docs/palettes/app/vue-components/color-slider.js
+++ b/docs/docs/palettes/app/vue-components/color-slider.js
@@ -32,18 +32,17 @@ export default {
return ['l', 'c', 'h'].includes(value);
},
},
- color: {
- type: Color,
- },
- defaultColor: {
- type: Color,
- },
+ color: Color,
+ defaultColor: Color,
- defaultValue: {
- type: Number,
- },
- /** Used for formatting only. Only specify if different from default value. */
- baseValue: {
+ defaultValue: Number,
+ defaultValueRelative: Number,
+
+ /** Used for relative types. Defaults to defaultValue if not provided. */
+ baseValue: Number,
+
+ /** Used for formatting only. Only specify if different from base value. */
+ formatBaseValue: {
type: Number,
default: undefined,
},
@@ -91,11 +90,7 @@ export default {
}
if (this.modelValue !== undefined) {
- this.value = getAbsoluteValue({
- type: this.type,
- relativeValue: this.modelValue,
- baseValue: this.computedDefaultValue,
- });
+ this.value = this.getAbsoluteValue(this.modelValue);
} else if (this.color) {
this.value = this.colorCoords[this.coordIndex];
}
@@ -114,11 +109,7 @@ export default {
computed: {
computedMin() {
if (this.minRelative !== undefined) {
- return getAbsoluteValue({
- type: this.type,
- relativeValue: this.minRelative,
- baseValue: this.computedDefaultValue,
- });
+ return getAbsoluteValue(this.minRelative);
}
return this.min;
@@ -126,11 +117,7 @@ export default {
computedMax() {
if (this.maxRelative !== undefined) {
- return getAbsoluteValue({
- type: this.type,
- relativeValue: this.maxRelative,
- baseValue: this.computedDefaultValue,
- });
+ return this.getAbsoluteValue(this.maxRelative);
}
return this.max;
@@ -183,8 +170,36 @@ export default {
return this.getColorAt(this.computedMax);
},
+ isRelative() {
+ return this.type && this.type !== 'raw';
+ },
+
+ computedBaseValue() {
+ if (!this.isRelative) {
+ return;
+ }
+
+ if (this.baseValue !== undefined) {
+ return this.baseValue;
+ }
+
+ return this.computedDefaultValue;
+ },
+
computedDefaultValue() {
- return this.defaultValue ?? this.defaultCoords[this.coordIndex];
+ if (this.defaultValue !== undefined) {
+ return this.defaultValue;
+ }
+
+ if (this.defaultValueRelative !== undefined) {
+ return this.getAbsoluteValue(this.defaultValueRelative);
+ }
+
+ if (this.baseValue !== undefined) {
+ return this.baseValue;
+ }
+
+ return this.defaultCoords[this.coordIndex];
},
computedDefaultColor() {
@@ -200,16 +215,37 @@ export default {
defaultProgress() {
return (this.computedDefaultValue - this.computedMin) / (this.computedMax - this.computedMin);
},
+
+ relativeValue() {
+ this.computedBaseValue;
+ return this.getRelativeValue(this.value);
+ },
},
methods: {
capitalize,
+ getAbsoluteValue(relativeValue) {
+ return getAbsoluteValue({
+ type: this.type,
+ relativeValue,
+ baseValue: this.baseValue ?? this.computedBaseValue,
+ });
+ },
+
+ getRelativeValue(absoluteValue) {
+ return getRelativeValue({
+ type: this.type,
+ absoluteValue,
+ baseValue: this.baseValue ?? this.computedBaseValue,
+ });
+ },
+
formatValue(value = this.value) {
let formatType = this.formatType ?? this.type;
let style = formatType === 'scale' ? 'percent' : undefined;
if (formatType && formatType !== 'raw') {
- let baseValue = this.baseValue ?? this.computedDefaultValue;
+ let baseValue = this.formatBaseValue ?? this.computedBaseValue;
value = getRelativeValue({ type: formatType, absoluteValue: value, baseValue });
}
@@ -227,15 +263,7 @@ export default {
handleInput(value) {
this.value = value;
this.tweaking = true;
-
- let modelValue = getRelativeValue({
- type: this.type,
- absoluteValue: value,
- baseValue: this.computedDefaultValue,
- });
-
- this.$emit('update:modelValue', modelValue);
- this.$emit('input', modelValue);
+ this.$emit('input', value);
},
inputEnd() {
@@ -261,16 +289,15 @@ export default {
if (this.colorCoords[this.coordIndex] !== this.value) {
this.value = this.colorCoords[this.coordIndex];
- let modelValue = getRelativeValue({
- type: this.type,
- absoluteValue: this.value,
- baseValue: this.computedDefaultValue,
- });
-
+ let modelValue = this.getRelativeValue(this.value);
this.$emit('update:modelValue', modelValue);
}
}
},
+
+ relativeValue() {
+ this.$emit('update:modelValue', this.relativeValue);
+ },
},
template,
components: { InfoTip },
diff --git a/docs/docs/palettes/app/vue-components/color-swatch.js b/docs/docs/palettes/app/vue-components/color-swatch.js
new file mode 100644
index 000000000..eb41d91cd
--- /dev/null
+++ b/docs/docs/palettes/app/vue-components/color-swatch.js
@@ -0,0 +1,85 @@
+const template = `
+
+
+
+
+
+
+
+
+
+`;
+
+import Color from 'https://colorjs.io/dist/color.js';
+import ColorPopup from './color-popup.js';
+import ColorSlider from './color-slider.js';
+import InfoTip from './info-tip.js';
+import { HUE_RANGES, hueAfter, hueBefore, hues, moreHue } from '/assets/scripts/tweak/data.js';
+import { capitalize, clamp, promise, roundTo } from '/assets/scripts/tweak/util.js';
+
+export default {
+ props: {
+ modelValue: Color,
+ hue: {
+ type: String,
+ required: true,
+ },
+ level: {
+ type: [String, Number],
+ required: true,
+ },
+ coreLevel: {
+ type: [String, Number],
+ required: true,
+ },
+ pinned: Boolean,
+ pinnable: Boolean,
+ deletable: Boolean,
+ colors: {
+ type: Object,
+ required: true,
+ },
+ tweakBase: [String, Number],
+ },
+ emits: ['update:modelValue', 'pin', 'delete'],
+ data() {
+ return {};
+ },
+ created() {
+ // Attach non-reactive data
+ Object.assign(this, { moreHue, HUE_RANGES });
+ },
+ computed: {
+ title() {
+ return capitalize(this.hue) + ' ' + this.level;
+ },
+ hueBefore() {
+ return hueBefore[this.hue];
+ },
+ hueAfter() {
+ return hueAfter[this.hue];
+ },
+ token() {
+ return `--wa-color-${this.hue}-${this.level}`;
+ },
+ isEdge() {
+ return this.level == '95' || this.level == '05';
+ },
+ isCore() {
+ return this.level == this.coreLevel;
+ },
+ },
+ methods: { capitalize },
+ template,
+ components: { InfoTip, ColorSlider, ColorPopup },
+ compilerOptions: {
+ isCustomElement: tag => tag.startsWith('wa-'),
+ },
+};