/
45case
/
ptable
Обзор
Документация
Войти
/
45case
/
ptable
Код
Запросы
3
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
dev
src/entities/table/ui/PropertyKey.vue
382 строки
12 KB
Olya
Страница Электроны + сайдбар с характеритстиками (Степень окисления, Конфигурация, Развёрнутая, Уровни энергии, ВЗМО)
24 июл 2026, 11:54
24 июл 2026, 11:54
3cf1d48
Код
Авторство
О чём код?
<script setup lang="ts"> import { computed } from "vue"; import type { PropertyScaleKind } from "../../element/lib/propertyColorScale"; const props = defineProps<{ startColor: string; endColor: string; unknownColor: string; scale: PropertyScaleKind; /** Melt/boil-style mid point; hidden for Weight. */ showZero?: boolean; zeroColor?: string; /** * Position of the zero stop in the legend gradient (0–100), ptable: * `Kelvin.value / Kelvin.max * 100`. Moves with the temperature slider. */ zeroStopPercent?: number; /** Ptable disables log scale when a temperature zero pivot is active. */ disableLogarithmic?: boolean; }>(); const emit = defineEmits<{ "update:startColor": [value: string]; "update:endColor": [value: string]; "update:unknownColor": [value: string]; "update:zeroColor": [value: string]; "update:scale": [value: PropertyScaleKind]; }>(); const gradientStyle = computed(() => { if (props.showZero && props.zeroColor) { const stop = Math.min(100, Math.max(0, props.zeroStopPercent ?? 50)); return { background: `linear-gradient(to bottom, ${props.startColor}, ${props.zeroColor} ${stop}%, ${props.endColor})`, }; } return { background: `linear-gradient(to bottom, ${props.startColor}, ${props.endColor})`, }; }); const unknownSwatchStyle = computed(() => ({ backgroundColor: props.unknownColor, })); function selectScale(next: PropertyScaleKind) { if (next === "log" && props.disableLogarithmic) { return; } emit("update:scale", next); } </script> <template> <div id="PropertyKey" class="property-key" aria-label="Легенда цвета свойства"> <dl class="property-key__colors"> <legend>Цвет</legend> <div class="property-key__colors-main"> <div class="property-key__color-labels"> <div class="property-key__color-row"> <label for="SchemeStart">Минимум</label> <input id="SchemeStart" type="color" name="SchemeStart" tabindex="0" :value="startColor" @input="emit('update:startColor', ($event.target as HTMLInputElement).value)" > </div> <div v-if="showZero" class="property-key__color-row"> <label for="SchemeZero">Ноль</label> <input id="SchemeZero" type="color" name="SchemeZero" tabindex="0" :value="zeroColor ?? '#ffffff'" @input="emit('update:zeroColor', ($event.target as HTMLInputElement).value)" > </div> <div class="property-key__color-row"> <label for="SchemeEnd">Максимум</label> <input id="SchemeEnd" type="color" name="SchemeEnd" tabindex="0" :value="endColor" @input="emit('update:endColor', ($event.target as HTMLInputElement).value)" > </div> </div> <div id="RangeGradient" class="property-key__gradient" :style="gradientStyle" /> </div> <div class="property-key__colors-unknown"> <div class="property-key__color-labels"> <div class="property-key__color-row"> <label for="SchemeUnknown">Неизвестный</label> <input id="SchemeUnknown" type="color" name="SchemeUnknown" tabindex="0" :value="unknownColor" @input="emit('update:unknownColor', ($event.target as HTMLInputElement).value)" > </div> </div> <div id="UnknownSwatch" class="property-key__unknown-swatch" :style="unknownSwatchStyle" /> </div> </dl> <dl class="property-key__scale-block"> <legend>Масштаб</legend> <div id="SchemeScale" class="property-key__scale" role="radiogroup" aria-label="Масштаб"> <button type="button" class="property-key__scale-option" :class="{ 'is-active': scale === 'lin' }" :aria-pressed="scale === 'lin'" @click.stop="selectScale('lin')" > <span class="property-key__scale-icon property-key__scale-icon--linear" aria-hidden="true" /> <span>Линейный</span> </button> <button type="button" class="property-key__scale-option" :class="{ 'is-active': scale === 'log' }" :aria-pressed="scale === 'log'" :disabled="disableLogarithmic" @click.stop="selectScale('log')" > <span class="property-key__scale-icon property-key__scale-icon--log" aria-hidden="true" /> <span>Логарифмический</span> </button> </div> </dl> </div> </template> <style scoped> .property-key { --property-key-pad: clamp(0.22rem, calc(var(--table-cell-size, 2.5rem) * 0.055), 0.42rem); --property-key-gap: clamp(0.18rem, calc(var(--table-cell-size, 2.5rem) * 0.045), 0.34rem); --property-key-track: clamp(0.8rem, calc(var(--table-cell-size, 2.5rem) * 0.2), 1.2rem); container-type: size; display: flex; flex-direction: row; align-items: stretch; gap: clamp(0.3rem, calc(var(--table-cell-size, 2.5rem) * 0.07), 0.55rem); box-sizing: border-box; width: 100%; max-width: 100%; height: 100%; min-height: 0; /* Room for overlapping «Цвет» / «Масштаб» legends above the borders. */ padding-top: 0.7em; overflow: hidden; user-select: none; color: var(--table-ink-strong); font-family: var(--table-font-ui, system-ui, sans-serif); font-size: clamp( 0.62rem, min(5.2cqh, 3.8cqw, calc(var(--table-cell-size, 2.5rem) * 0.155)), 1.02rem ); pointer-events: auto; } .property-key__colors, .property-key__scale-block { position: relative; display: flex; justify-content: space-between; gap: var(--property-key-gap); margin: 0; min-height: 0; padding: calc(var(--property-key-pad) * 1.45) var(--property-key-pad) var(--property-key-pad); border: 1px solid var(--table-selected-line, var(--table-line)); border-radius: var(--property-key-pad); background: color-mix(in oklab, var(--table-surface) 92%, var(--color-surface)); pointer-events: auto; } /* Color ~35%, Scale ~65%. */ .property-key__colors { flex: 35 1 0; flex-direction: column; min-width: 0; width: 35%; } .property-key__scale-block { flex: 65 1 0; flex-direction: row; align-items: stretch; min-width: 0; width: 65%; } .property-key__colors > legend, .property-key__scale-block > legend { position: absolute; top: 0; left: var(--property-key-pad); z-index: 1; margin-top: calc(-0.5em); padding-inline: 0.25em; background: color-mix(in oklab, var(--table-surface) 92%, var(--color-surface)); line-height: 1; font-size: 0.95em; font-weight: 650; pointer-events: none; } .property-key__colors-main, .property-key__colors-unknown { display: flex; justify-content: flex-end; white-space: nowrap; min-height: 0; } .property-key__colors-main { flex: 1 1 auto; } .property-key__colors-unknown { flex: 0 0 auto; color: color-mix(in oklab, var(--table-ink-strong) 55%, #888); margin-top: 0.28em; } .property-key__color-labels { display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end; line-height: 1; gap: 0.35em; } .property-key__color-row { display: flex; align-items: center; gap: 0.28em; } .property-key__color-row label { cursor: pointer; } .property-key__color-row input[type="color"] { width: clamp(1.7rem, calc(var(--table-cell-size, 2.5rem) * 0.45), 2.3rem); height: clamp(1.15rem, calc(var(--table-cell-size, 2.5rem) * 0.3), 1.45rem); padding: 0; border: 1px solid color-mix(in oklab, var(--table-line) 80%, #888); border-radius: 0.15rem; background: transparent; cursor: pointer; } .property-key__gradient, .property-key__unknown-swatch { width: var(--property-key-track); margin-inline-start: 0.45em; border: 1px solid color-mix(in oklab, var(--table-line) 80%, #888); border-radius: 0.1rem; flex-shrink: 0; } .property-key__gradient { align-self: stretch; min-height: 100%; } .property-key__unknown-swatch { min-height: clamp(1rem, calc(var(--table-cell-size, 2.5rem) * 0.26), 1.35rem); align-self: center; } .property-key__scale { display: flex; flex: 1; align-items: stretch; justify-content: space-evenly; gap: 0.15rem; min-height: 0; min-width: 0; margin: 0; padding: 0; } .property-key__scale-option { display: flex; flex-direction: column; align-items: center; flex-grow: 1; flex: 1 1 0; width: auto; min-width: 0; margin: 0; padding: var(--property-key-pad) calc(var(--property-key-pad) * 1.2); border: 2px solid transparent; border-radius: 0.28rem; background: transparent; color: color-mix(in oklab, var(--table-ink-strong) 72%, transparent); font: inherit; font-weight: 520; font-size: 0.92em; line-height: 1.35; cursor: pointer; pointer-events: auto; position: relative; z-index: 2; transition: background-color 140ms ease, border-color 140ms ease, box-shadow 140ms ease, color 140ms ease; } .property-key__scale-option.is-active { color: var(--table-ink-strong); font-weight: 700; background: color-mix(in oklab, var(--color-selected-surface, #ddd) 78%, var(--table-surface)); border-color: color-mix(in oklab, var(--color-selected-border, #888) 88%, var(--table-selected-line)); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--color-selected-border, #888) 35%, transparent), 0 0 0 1px color-mix(in oklab, var(--color-selected-border, #888) 22%, transparent); } .property-key__scale-option:hover:not(.is-active) { color: var(--table-ink-strong); background: color-mix(in oklab, var(--table-selected-surface) 48%, transparent); } .property-key__scale-option:disabled { opacity: 0.45; cursor: not-allowed; pointer-events: none; } .property-key__scale-option:not(.is-active) .property-key__scale-icon { opacity: 0.72; } .property-key__scale-option.is-active .property-key__scale-icon { opacity: 1; } /* Ptable: label::before width 5.5em + flex-grow fills the panel. */ .property-key__scale-icon { content: ""; display: block; flex-grow: 1; width: min(5.5em, 100%); max-width: 100%; min-height: min(4.2em, 48cqh); background-size: contain; background-repeat: no-repeat; background-position: center; pointer-events: none; } .property-key__scale-icon--linear { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E %3Cdefs%3E %3Cmarker id='arrow' markerWidth='10' markerHeight='10' refX='5' refY='5' orient='auto'%3E %3Cpolyline points='3,3 5,5 3,7' fill='none' stroke='%23555' /%3E %3C/marker%3E %3C/defs%3E %3Cg stroke='%23555' stroke-width='3'%3E %3Cline x1='10' y1='100' x2='10' y2='10' marker-end='url(%23arrow)' /%3E %3Cline x1='0' y1='90' x2='90' y2='90' marker-end='url(%23arrow)' /%3E %3Cline x1='20' y1='80' x2='80' y2='20' /%3E %3C/g%3E%3C/svg%3E"); } .property-key__scale-icon--log { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E %3Cdefs%3E %3Cmarker id='arrow' markerWidth='10' markerHeight='10' refX='5' refY='5' orient='auto'%3E %3Cpolyline points='3,3 5,5 3,7' fill='none' stroke='%23555' /%3E %3C/marker%3E %3C/defs%3E %3Cg stroke='%23555' stroke-width='3'%3E %3Cline x1='10' y1='100' x2='10' y2='10' marker-end='url(%23arrow)' /%3E %3Cline x1='0' y1='90' x2='90' y2='90' marker-end='url(%23arrow)' /%3E %3Cpath d='M20,80 Q20,20 80,20' fill='none' /%3E %3C/g%3E%3C/svg%3E"); } html[data-theme="dark"] .property-key__scale-icon { filter: invert(1); } </style>