UNPKG

@browser.style/data-entry

Version:

Dynamic data entry form component with JSON schema validation and internationalization support

570 lines (509 loc) 13.1 kB
@import url('../icon/index.css'); @layer bs-component { :where(data-entry) { --_bdc: var(--ButtonBorder); --_bgc: var(--CanvasGray); --_bdrs: var(--input-bdrs); --_bdw: var(--input-bdw); --_lblw: 75px; --_pb: .6ch; --_pi: 1.2ch; --_rg: 1lh; display: grid; & *:not(ui-icon) { font-size: clamp(0.8125rem, 0.7091rem + 0.5172vw, 1rem); } /* === PARTS === */ [part~=autosuggest], [part~=datamapper] { --_bdrs: 0; &:not([form]) { display: contents; & [part~="row"]:first-of-type { border-block-start-width: 0; } } &[form] { border: var(--_bdw) solid var(--_bdc); border-radius: var(--input-bdrs); margin-block-end: 1ch; label { display: contents; } span { display: none; } } } [part~=datamapper] { [part~="filewrap"] { align-items: center; display: flex; justify-content: space-between; padding-inline: var(--_pi); } [part~="processed"] { color: var(--ColorInfo); font-size: small; white-space: nowrap; } [type="file"] { --button-p: 3px 6px; font-size: small; width: fit-content; } abbr { color: var(--ColorError); margin-inline: .25ch 1ch; text-decoration: none; } } [part~=close] { background-color: #0000; border-color: var(--_bdc); margin-inline-end: auto; } [part~=delete] { --input-check-bg: var(--CanvasGray); --input-check-bga: var(--CanvasText); --icon: url('./assets/svg/cross.svg'); } /* === Details === */ [part~=array-details] { summary label { column-gap: 0; } summary { & [part~=value] { align-items: center; column-gap: 1ch; display: flex; font-weight: 400; text-wrap: nowrap; } & output { display: flex; flex: 1; font-style: normal; gap: 2ch; justify-content: space-between; pointer-events: none; text-wrap: balance; & > :first-child { flex: 1; } } & label { margin-inline-start: auto; } } details:has(summary input[type=checkbox]:not(:checked)) { background: color-mix(in srgb, var(--ColorError), var(--Canvas) 80%); color: var(--GrayText); text-decoration: line-through; summary input[type=checkbox] { background-color: var(--ColorError); --input-check-bdc: var(--ColorError); --input-check-bga: #FFF; } input:not([type=checkbox]) { background-color: #0000; } } details:not(:first-of-type):not(:last-of-type) summary { border-block-start-width: 0; border-radius: 0; } details:first-of-type:not(:only-of-type) summary { border-end-start-radius: 0; border-end-end-radius: 0; } details:last-of-type:not(:only-of-type) summary { border-block-start-width: 0; border-start-start-radius: 0; border-start-end-radius: 0; } &[open] { background-color: light-dark(hsl(211, 100%, 90%), hsl(211, 60%, 90%)); & input:not([type=checkbox]) { background-color: #0000; } } label:first-of-type { --_bdrs: 0; } } fieldset[part~=array-details] { /* === Array has no children, add border to legend and padding to (optional) nav */ &:not(:has(details)) { & > legend { border-block-end: var(--_bdw) solid var(--_bdc); } } /* === No nav-element was found, hide */ &:not(:has(details, nav)) { display: none; } } [part~=array-link] { a { color: inherit; } [part~=value] { padding-inline: var(--_pi); } } /* === Array Unit === */ fieldset[part~=array-unit] { border-color: var(--_bdc); border-style: solid; border-width: 0 var(--_bdw) var(--_bdw); font-variant-numeric: tabular-nums; grid-template-columns: var(--_lblw) 1fr 9ch 9ch min-content; &:not(:first-of-type):not(:last-of-type) { border-radius: 0; [part~=row] input[part=input] { border-radius: 0; } } &:first-of-type { border-block-start-width: var(--_bdw); &:not(:last-of-type) { border-end-start-radius: 0; border-end-end-radius: 0; input[part=input] { border-radius: calc(var(--_bdrs) - var(--_bdw)) 0 0 0; } } } &:last-of-type { &:not(:first-of-type) { border-start-start-radius: 0; border-start-end-radius: 0; input[part=input] { border-radius: 0 0 0 calc(var(--_bdrs) - var(--_bdw)); } } } & > label { grid-template-columns: 1fr; margin-inline: var(--_pi); place-self: center; } label[part=row] { display: contents; } output { display: contents; & > span { border-inline-start: var(--_bdw) solid var(--_bdc); padding: var(--_pb) var(--_pi); place-content: center; &:not(:first-of-type) { text-align: end; } &:not(:only-of-type):last-of-type { border-inline-end: var(--_bdw) solid var(--_bdc); } } } span[part=label] { display: none; } } [part~=fieldset] { border: 0; gap: 0; padding: 0; } /* TODO part form and part content */ [part~=form], [part~=footer] { display: grid; row-gap: calc(var(--_rg) / 3); [part~=nav] { row-gap: calc(var(--_rg) / 3); } } [part~=main-nav] { background-color: Canvas; display: flex; flex-wrap: wrap; gap: .75ch; padding-block: .75ch; position: sticky; top: 0; z-index: 10; a { background: var(--_bgc); border-radius: var(--_bdrs); color: inherit; font-size: small; padding: .5ch 1ch; text-decoration: none; &.visible { /* --_bgc: hotpink; */ &.active { --_bgc: var(--AccentColor); color: var(--AccentColorText); } } } } [part~=main] { display: grid; row-gap: var(--_rg); } [part~=title] { font-size: 150%; font-weight: 700; line-height: 1.3; } @supports (animation-timeline: scroll()) { [part~=main-nav] { animation: scroll-shadow linear both; animation-timeline: scroll(); animation-range: 0ex 5ex; } } @media (min-width: 600px) { --_lblw: 125px; } /* ARRAY GRID */ [part~=array-grid] { fieldset { border: 0; border-radius: 0; padding: 0; row-gap: 0; } @media (max-width: 599px) { margin-block-start: var(--_rg); fieldset { &:not(:last-of-type) { margin-block-end: var(--_rg); } } } @media (min-width: 600px) { & { --_bdrs: 0; background: var(--_bdc); margin-block-start: var(--_rg); padding: var(--_bdw); position: relative; row-gap: var(--_bdw); } legend { inset-block-start: calc(0lh - var(--_rg)); position: absolute; } label[part~=row] { border: 0; grid-template-columns: unset; row-gap: 0; span { border: 0; border-radius: inherit !important; } } fieldset { column-gap: var(--_bdw); grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); /* Only show the labels from first row */ &:nth-of-type(n+2) label > span { display: none; } /* Hide UI Icons */ & :is(input, select, textarea) { --icon: none; } &:first-of-type label { span { border-bottom: var(--_bdc) solid var(--_bdw); } &:first-of-type { border-start-start-radius: var(--input-bdrs); } &:last-of-type { border-start-end-radius: var(--input-bdrs); } } &:last-of-type label { &:first-of-type { border-end-start-radius: var(--input-bdrs); } &:last-of-type { border-end-end-radius: var(--input-bdrs); } & input { border-radius: inherit !important;} } } } } [part~=input]:not([type=checkbox],[type=radio]), [part~=select], [part~=textarea] { block-size: 100%; border: 0; border-radius: 0; font-family: inherit; padding-block: var(--_pb); &::-webkit-inner-spin-button{ display: none; } } [part~=label] { align-items: center; background-color: var(--_bgc); border-inline-end: var(--_bdw) solid var(--_bdc); column-gap: 1ch; display: block; font-weight: 500; height: 100%; overflow: hidden; padding: var(--_pb) var(--_pi); text-overflow: ellipsis; white-space: nowrap; summary & { display: flex;} } [part~=legend] { font-weight: 700; width: 100%; } [part~=media] { gap: var(--_pi); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); label { border-width: var(--_bdw); border-radius: var(--_bdrs); grid-template-columns: 1fr; padding: var(--_pi); img { aspect-ratio: 1 / 1; grid-area: 1 / 1; height: 100%; object-fit: contain; place-self: center; user-drag: none; -webkit-user-drag: none; width: 100%; } input { grid-area: 1 / 1; place-self: end; } &:has(input:not(:checked)) { background: color-mix(in srgb, var(--ColorError), var(--Canvas) 80%); img { opacity: .25; } input { background-color: var(--ColorError); --input-check-bdc: var(--ColorError); --input-check-bga: #FFF; } } } } [part~=micro] { background: #0000; color: var(--LinkText); font-family: inherit; font-size: x-small; padding: 0; } [part~=nav] { column-gap: 1ch; display: flex; flex-wrap: wrap; justify-content: end; padding-block-start: .33lh; [part~=link] { font-size: x-small; font-weight: 500; &[part~=action] { background: var(--ButtonFace); color: inherit; padding: .25ch 1ch; border-radius: 2px; text-decoration: none; } } &[part~=actions] { padding-block-start: 0; } [popovertarget] { cursor: pointer; } } [part~=richtext] { --ui-richtext-active-bg: var(--AccentColor); --ui-richtext-active-c: var(--AccentColorText); padding: var(--_pi); &::part(toolbar) { padding-block-end: var(--_pb); } } [part~=row] { align-items: center; border-block-width: 0 var(--_bdw); border-inline-width: var(--_bdw); border-color: var(--_bdc); border-style: solid; display: grid; grid-template-columns: var(--_lblw) 1fr; user-select: none; &[part~=action] { grid-template-columns: var(--_lblw) 1fr min-content; & > button { font-size: small; margin-inline-end: var(--_pb); padding: .25ch .75ch; } } abbr { margin: 0; } &:first-of-type:not(div) { border-block-start-width: var(--_bdw); border-start-start-radius: var(--_bdrs); border-start-end-radius: var(--_bdrs); & > *:first-child { border-start-start-radius: var(--_bdrs); } & > *:last-child { border-start-end-radius: calc(var(--_bdrs) - var(--_bdw)); } } &:last-of-type:not(div) { border-end-start-radius: var(--_bdrs); border-end-end-radius: var(--_bdrs); & > *:first-child { border-end-start-radius: var(--_bdrs); } & > *:last-child { border-end-end-radius: calc(var(--_bdrs) - var(--_bdw)); } } &:is(summary) { [part~=value] { padding-inline: var(--_pi); } [open] & { border-block-end-width: 0;; border-end-start-radius: 0; border-end-end-radius: 0; & + fieldset label:first-of-type { border-start-start-radius: 0; border-start-end-radius: 0; } } &::-webkit-details-marker { display: none; } } [part~=link] { padding-inline: var(--_pi); } } [part~=textarea] { textarea { field-sizing: content; min-block-size: 2.4lh; resize: vertical; } } [part~=toolbar] { margin-block-start: .5lh; } /* WIP */ [data-lastpass-icon-root] { display: none; } div[popover] { border: var(--_bdw) solid var(--_bdc); border-radius: var(--_bdrs); box-shadow: 0px 25px 50px -12px color-mix(in srgb, CanvasText 25%, transparent); inset-block: anchor(bottom) auto; inset-inline: auto anchor(right); min-inline-size: 20rem; padding: 2ch; position-anchor: var(--_pa); position-try-fallbacks: flip-block; text-wrap: nowrap; &::backdrop { background: light-dark(#0002, #000A); } [dir=rtl] & { inset-inline: auto anchor(left); } nav { margin-block-start: 1ch; } } [popovertarget] { anchor-name: var(--_an); } /* Focus */ :is(input:not([type=checkbox], [type=radio]), select, summary, textarea):focus-visible, input[type=date]:focus-within, label:has([type=checkbox], [type=radio]):focus-within, ui-richtext:focus-within { background-color: var(--CanvasGray); outline: 2px solid var(--AccentColor); outline-offset: -2px; & * { outline: none; } } label:has([type=checkbox], [type=radio]):focus-within + label:not(:has([part=img])), [part~="array-details"]:has(summary:focus-visible) + [part~="array-details"] summary [part~="label"] { clip-path: inset(2px 0 0 0); } label:has([part~=delete]):focus-within { outline-offset: 2px; } [part~=media] label:focus-within { outline-offset: -2px; } /* details:not([open]):focus-within + details */ } } /* TODO */ .mie-auto { margin-inline-end: auto; } @keyframes scroll-shadow { from { box-shadow: none; } to { box-shadow: 0px .8em .4em -.4em var(--_bdc); } }