UNPKG

sober

Version:

Sober is a library of UI components designed with reference to Material You.

222 lines (221 loc) 5.83 kB
import { useElement, useProps } from './core/element.js'; import './ripple.js'; const name = 's-field'; const props = useProps({ focused: false, fixed: true }); const style = /*css*/ ` :host{ display: inline-block; vertical-align: middle; font-size: .875rem; --field-padding: 16px; --field-padding-top: var(--field-padding); --field-padding-bottom: var(--field-padding); --field-padding-left: var(--field-padding); --field-padding-right: var(--field-padding); --field-border-radius: 4px; --field-border-width: 1px; --field-focused-border-width: 2px; --field-border-color: var(--s-color-outline, ${"#70787D" /* Theme.colorOutline */}); } .container{ display: flex; height: 100%; min-height: inherit; } .line{ position: relative; } .line::before, .line::after{ position: absolute; content: ''; top: 0; left: 0; height: 100%; width: 100%; box-sizing: border-box; border-width: var(--field-border-width); border-color: var(--field-border-color); pointer-events: none; } .line::after{ border-width: var(--field-focused-border-width); border-color: var(--s-color-primary, ${"#006782" /* Theme.colorPrimary */}); opacity: 0; transition: opacity .2s ease-out; } :host([focused=true]) .line::after{ opacity: 1; } .start, .end{ display: flex; align-items: center; flex-shrink: 0; min-width: var(--field-border-radius); } .start::before, .end::before, .start::after, .end::after{ border-top-style: solid; border-bottom-style: solid; } .start::before, .start::after{ border-left-style: solid; border-top-left-radius: var(--field-border-radius); border-bottom-left-radius: var(--field-border-radius); } .end::before, .end::after{ border-right-style: solid; border-top-right-radius: var(--field-border-radius); border-bottom-right-radius: var(--field-border-radius); left: auto; right: 0; } .box{ display: grid; grid-template-areas: "a" "a"; flex-grow: 1; } .box::before, .box::after{ border-bottom-style: solid; } .top, .view{ height: 100%; display: flex; grid-area: a; position: relative; box-sizing: border-box; margin-left: calc(var(--field-border-radius) * -1); margin-right: calc(var(--field-border-radius) * -1); } .view{ align-items: center; } .top{ pointer-events: none; } .top>.left::before, .top>.right::before, .top>.left::after, .top>.right::after{ border-top-style: solid; } .top>.left{ width: calc(var(--field-padding-left) - var(--field-border-radius) - 4px); margin-left: max(4px, var(--field-border-radius)); margin-right: min(4px, calc(var(--field-padding-left) - var(--field-border-radius))); flex-shrink: 0; } :host([fixed=false]) .top>.left{ width: calc(var(--field-padding-left) - var(--field-border-radius)); margin-right: 0; } .top>.right{ flex-grow: 1; width: calc(var(--field-padding-right) - var(--field-border-radius) - 4px); margin-left: min(4px, calc(var(--field-padding-right) - var(--field-border-radius))); margin-right: max(4px, var(--field-border-radius)); } :host([fixed=false]) .top>.right{ width: calc(var(--field-padding-left) - var(--field-border-radius)); margin-left: 0; } .label{ display: block; height: 100%; flex-shrink: 0; } .label>.line::before, .label>.line::after, :host([fixed=false]) .label::before, :host([fixed=false]) .label::after{ border-top-style: solid; } .label>.line::before, .label>.line::after{ transform: translateX(-50%); width: min(calc(var(--field-padding-right) - var(--field-border-radius)), 8px); } ::slotted([slot=label]){ display: flex; align-items: center; height: 100%; font-size: .75rem; align-items: center; transform: translateY(-50%); color: var(--field-border-color); transition: transform .2s ease-out, font-size .2s ease-out; box-sizing: border-box; position: relative; } :host([fixed=false]) ::slotted([slot=label]), ::slotted([slot=label]:empty){ font-size: inherit; transform: translateY(0); } ::slotted([slot=label]:empty)::before, ::slotted([slot=label]:empty)::after{ content: ''; position: absolute; top: 0; left: 0; transform: translateX(-50%); width: min(calc(var(--field-padding-right) - var(--field-border-radius)), 8px); border-top: solid var(--field-border-width); var(--field-border-color); } ::slotted([slot=label]:empty)::after{ opacity: 0; border-width: var(--field-focused-border-width); transition: opacity .2s ease-out; border-color: var(--s-color-primary, ${"#006782" /* Theme.colorPrimary */}); } :host([focused=true]) ::slotted([slot=label]:empty)::after{ opacity: 1; } :host([focused=true]) ::slotted([slot=label]){ color: var(--s-color-primary, ${"#006782" /* Theme.colorPrimary */}); } ::slotted(:not([slot])){ padding-left: var(--field-padding-left); padding-right: var(--field-padding-right); padding-top: var(--field-padding-top); padding-bottom: var(--field-padding-bottom); display: flex; align-items: center; height: 100%; box-sizing: border-box; } `; const template = /*html*/ ` <div class="container" part="container"> <div class="start line" part="start"> <slot name="start"></slot> </div> <div class="box line" part="box"> <slot class="view"></slot> <div class="top" part="top"> <div class="line left"></div> <slot name="label" class="label line"> <div class="line"></div> </slot> <div class="line right"></div> </div> </div> <div class="end line" part="end"> <slot name="end"></slot> </div> <slot name="custom"></slot> </div> `; export class Field extends useElement({ style, template, props }) { } Field.define(name);