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-'), + }, +};