mirror of
https://github.com/ducbao414/win32.run.git
synced 2025-12-16 17:22:51 +09:00
init the awkward code
This commit is contained in:
778
static/html/jspaint/lib/98.css/98.custom-build.css
Normal file
778
static/html/jspaint/lib/98.css/98.custom-build.css
Normal file
@@ -0,0 +1,778 @@
|
||||
/*! 98.css custom build - https://github.com/jdan/98.css */
|
||||
/**
|
||||
* 98.css
|
||||
* Copyright (c) 2020 Jordan Scales <thatjdanisso.cool>
|
||||
* https://github.com/jdan/98.css/blob/main/LICENSE
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Color */
|
||||
--surface: var(--ButtonFace, #c0c0c0);
|
||||
--button-highlight: var(--ButtonHilight, #ffffff);
|
||||
--button-face: var(--ButtonFace, #dfdfdf);
|
||||
--button-shadow: var(--ButtonShadow, #808080);
|
||||
--window-frame: var(--WindowFrame, #0a0a0a);
|
||||
--dialog-blue: var(--ActiveTitle, #000080);
|
||||
--dialog-blue-light: var(--GradientActiveTitle, #1084d0);
|
||||
--dialog-gray: var(--InactiveTitle, #808080);
|
||||
--dialog-gray-light: var(--GradientInactiveTitle, #b5b5b5);
|
||||
--link-blue: #0000ff;
|
||||
|
||||
/* Spacing */
|
||||
--element-spacing: 8px;
|
||||
--grouped-button-spacing: 4px;
|
||||
--grouped-element-spacing: 6px;
|
||||
--radio-width: 12px;
|
||||
--checkbox-width: 13px;
|
||||
--radio-label-spacing: 6px;
|
||||
--range-track-height: 4px;
|
||||
--range-spacing: 10px;
|
||||
|
||||
/* Some detailed computations for radio buttons and checkboxes */
|
||||
--radio-total-width-precalc: var(--radio-width) + var(--radio-label-spacing);
|
||||
--radio-total-width: calc(var(--radio-total-width-precalc));
|
||||
--radio-left: calc(-1 * var(--radio-total-width-precalc));
|
||||
--radio-dot-width: 4px;
|
||||
--radio-dot-top: calc(var(--radio-width) / 2 - var(--radio-dot-width) / 2);
|
||||
--radio-dot-left: calc(
|
||||
-1 * (var(--radio-total-width-precalc)) + var(--radio-width) / 2 - var(
|
||||
--radio-dot-width
|
||||
) / 2
|
||||
);
|
||||
|
||||
--checkbox-total-width-precalc: var(--checkbox-width) +
|
||||
var(--radio-label-spacing);
|
||||
--checkbox-total-width: calc(var(--checkbox-total-width-precalc));
|
||||
--checkbox-left: calc(-1 * var(--checkbox-total-width-precalc));
|
||||
--checkmark-width: 7px;
|
||||
--checkmark-top: 3px;
|
||||
--checkmark-left: 3px;
|
||||
|
||||
/* Borders */
|
||||
--border-width: 1px;
|
||||
/* rtl:ignore */
|
||||
--border-raised-outer: inset -1px -1px var(--window-frame),
|
||||
inset 1px 1px var(--button-highlight);
|
||||
/* rtl:ignore */
|
||||
--border-raised-inner: inset -2px -2px var(--button-shadow),
|
||||
inset 2px 2px var(--button-face);
|
||||
/* rtl:ignore */
|
||||
--border-sunken-outer: inset -1px -1px var(--button-highlight),
|
||||
inset 1px 1px var(--window-frame);
|
||||
/* rtl:ignore */
|
||||
--border-sunken-inner: inset -2px -2px var(--button-face),
|
||||
inset 2px 2px var(--button-shadow);
|
||||
|
||||
/* Window borders flip button-face and button-highlight */
|
||||
/* rtl:ignore */
|
||||
--border-window-outer: inset -1px -1px var(--window-frame),
|
||||
inset 1px 1px var(--button-face);
|
||||
/* rtl:ignore */
|
||||
--border-window-inner: inset -2px -2px var(--button-shadow),
|
||||
inset 2px 2px var(--button-highlight);
|
||||
|
||||
/* Field borders (checkbox, input, etc) flip window-frame and button-shadow */
|
||||
/* rtl:ignore */
|
||||
--border-field: inset -1px -1px var(--button-highlight),
|
||||
inset 1px 1px var(--button-shadow), inset -2px -2px var(--button-face),
|
||||
inset 2px 2px var(--window-frame);
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: "Pixelated MS Sans Serif";
|
||||
src: url("fonts/converted/ms_sans_serif.woff") format("woff");
|
||||
src: url("fonts/converted/ms_sans_serif.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Pixelated MS Sans Serif";
|
||||
src: url("fonts/converted/ms_sans_serif_bold.woff") format("woff");
|
||||
src: url("fonts/converted/ms_sans_serif_bold.woff2") format("woff2");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
button,
|
||||
label,
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
option,
|
||||
ul.tree-view,
|
||||
.window,
|
||||
.title-bar {
|
||||
font-family: "Pixelated MS Sans Serif", Arial;
|
||||
-webkit-font-smoothing: none;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
u {
|
||||
text-decoration: none;
|
||||
border-bottom: 0.5px solid #222222;
|
||||
}
|
||||
|
||||
button {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
background: var(--surface);
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
border-radius: 0;
|
||||
|
||||
min-width: 75px;
|
||||
min-height: 23px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.vertical-bar {
|
||||
width: 4px;
|
||||
height: 20px;
|
||||
background: #c0c0c0;
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
}
|
||||
|
||||
button:not(:disabled):active {
|
||||
box-shadow: var(--border-sunken-outer), var(--border-sunken-inner);
|
||||
padding: 2px 11px 0 13px;
|
||||
}
|
||||
|
||||
@media (not(hover)) {
|
||||
button:not(:disabled):hover {
|
||||
box-shadow: var(--border-sunken-outer), var(--border-sunken-inner);
|
||||
}
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px dotted #000000;
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
:disabled,
|
||||
:disabled + label {
|
||||
color: var(--button-shadow);
|
||||
}
|
||||
|
||||
button:disabled,
|
||||
:disabled + label {
|
||||
text-shadow: 1px 1px 0 var(--button-highlight);
|
||||
}
|
||||
|
||||
.window {
|
||||
box-shadow: var(--border-window-outer), var(--border-window-inner);
|
||||
background: var(--surface);
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--dialog-blue),
|
||||
var(--dialog-blue-light)
|
||||
);
|
||||
padding: 3px 2px 3px 3px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title-bar.inactive {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--dialog-gray),
|
||||
var(--dialog-gray-light)
|
||||
);
|
||||
}
|
||||
|
||||
.title-bar-text {
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
letter-spacing: 0;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.title-bar-controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title-bar-controls button {
|
||||
padding: 0;
|
||||
display: block;
|
||||
min-width: 16px;
|
||||
min-height: 14px;
|
||||
}
|
||||
|
||||
.title-bar-controls button:active {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.title-bar-controls button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Minimize"] {
|
||||
background-image: svg-load("./icon/minimize.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: bottom 3px left 4px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Maximize"] {
|
||||
background-image: svg-load("./icon/maximize.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 3px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Restore"] {
|
||||
background-image: svg-load("./icon/restore.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 3px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Help"] {
|
||||
background-image: svg-load("./icon/help.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 5px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Close"] {
|
||||
margin-left: 2px;
|
||||
background-image: svg-load("./icon/close.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 3px left 4px;
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
margin: 0px 1px;
|
||||
display: flex;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.status-bar-field {
|
||||
box-shadow: inset -1px -1px #dfdfdf,
|
||||
inset 1px 1px #808080;
|
||||
flex-grow: 1;
|
||||
padding: 2px 3px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.window-body {
|
||||
margin: var(--element-spacing);
|
||||
}
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='5' height='5' viewBox='0 0 5 5' fill='grey' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0H5V5H0V2H2V3H3V2H0' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0H4V4H0V1H1V3H3V1H0' fill='%23808080'/%3E %3C/svg%3E") 2;
|
||||
padding: calc(2 * var(--border-width) + var(--element-spacing));
|
||||
padding-block-start: var(--element-spacing);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
/* .field-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
[class^="field-row"] + [class^="field-row"] {
|
||||
margin-top: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row > * + * {
|
||||
margin-left: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row-stacked {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.field-row-stacked * + * {
|
||||
margin-top: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
} */
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
background: 0;
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
input[type="radio"] + label,
|
||||
input[type="checkbox"] + label {
|
||||
line-height: 13px;
|
||||
}
|
||||
|
||||
input[type="radio"] + label {
|
||||
position: relative;
|
||||
margin-left: var(--radio-total-width);
|
||||
}
|
||||
|
||||
input[type="radio"] + label::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: calc(-1 * (var(--radio-total-width-precalc)));
|
||||
display: inline-block;
|
||||
width: var(--radio-width);
|
||||
height: var(--radio-width);
|
||||
margin-right: var(--radio-label-spacing);
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 0H4V1H2V2H1V4H0V8H1V10H2V8H1V4H2V2H4V1H8V2H10V1H8V0Z' fill='%23808080'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 1H4V2H2V3V4H1V8H2V9H3V8H2V4H3V3H4V2H8V3H10V2H8V1Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 3H10V4H9V3ZM10 8V4H11V8H10ZM8 10V9H9V8H10V9V10H8ZM4 10V11H8V10H4ZM4 10V9H2V10H4Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 2H10V4H11V8H10V10H8V11H4V10H2V11H4V12H8V11H10V10H11V8H12V4H11V2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2H8V3H9V4H10V8H9V9H8V10H4V9H3V8H2V4H3V3H4V2Z' fill='white'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="radio"]:active + label::before {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 0H4V1H2V2H1V4H0V8H1V10H2V8H1V4H2V2H4V1H8V2H10V1H8V0Z' fill='%23808080'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 1H4V2H2V3V4H1V8H2V9H3V8H2V4H3V3H4V2H8V3H10V2H8V1Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 3H10V4H9V3ZM10 8V4H11V8H10ZM8 10V9H9V8H10V9V10H8ZM4 10V11H8V10H4ZM4 10V9H2V10H4Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 2H10V4H11V8H10V10H8V11H4V10H2V11H4V12H8V11H10V10H11V8H12V4H11V2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2H8V3H9V4H10V8H9V9H8V10H4V9H3V8H2V4H3V3H4V2Z' fill='%23C0C0C0'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="radio"]:checked + label::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: var(--radio-dot-width);
|
||||
height: var(--radio-dot-width);
|
||||
top: var(--radio-dot-top);
|
||||
left: var(--radio-dot-left);
|
||||
position: absolute;
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='4' height='4' viewBox='0 0 4 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M3 0H1V1H0V2V3H1V4H3V3H4V2V1H3V0Z' fill='black'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="radio"]:focus + label,
|
||||
input[type="checkbox"]:focus + label {
|
||||
outline: 1px dotted #000000;
|
||||
}
|
||||
|
||||
input[type="radio"][disabled] + label::before {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 0H4V1H2V2H1V4H0V8H1V10H2V8H1V4H2V2H4V1H8V2H10V1H8V0Z' fill='%23808080'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 1H4V2H2V3V4H1V8H2V9H3V8H2V4H3V3H4V2H8V3H10V2H8V1Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 3H10V4H9V3ZM10 8V4H11V8H10ZM8 10V9H9V8H10V9V10H8ZM4 10V11H8V10H4ZM4 10V9H2V10H4Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 2H10V4H11V8H10V10H8V11H4V10H2V11H4V12H8V11H10V10H11V8H12V4H11V2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2H8V3H9V4H10V8H9V9H8V10H4V9H3V8H2V4H3V3H4V2Z' fill='%23C0C0C0'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="radio"][disabled]:checked + label::after {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='4' height='4' viewBox='0 0 4 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M3 0H1V1H0V2V3H1V4H3V3H4V2V1H3V0Z' fill='%23808080'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="checkbox"] + label {
|
||||
position: relative;
|
||||
margin-left: var(--checkbox-total-width);
|
||||
}
|
||||
|
||||
input[type="checkbox"] + label::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: calc(-1 * (var(--checkbox-total-width-precalc)));
|
||||
display: inline-block;
|
||||
width: var(--checkbox-width);
|
||||
height: var(--checkbox-width);
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
margin-right: var(--radio-label-spacing);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:active + label::before {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked + label::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: var(--checkmark-width);
|
||||
height: var(--checkmark-width);
|
||||
position: absolute;
|
||||
top: var(--checkmark-top);
|
||||
left: calc(
|
||||
-1 * (var(--checkbox-total-width-precalc)) + var(--checkmark-left)
|
||||
);
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='7' height='7' viewBox='0 0 7 7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 0H6V1H5V2H4V3H3V4H2V3H1V2H0V5H1V6H2V7H3V6H4V5H5V4H6V3H7V0Z' fill='black'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="checkbox"][disabled] + label::before {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
input[type="checkbox"][disabled]:checked + label::after {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='7' height='7' viewBox='0 0 7 7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 0H6V1H5V2H4V3H3V4H2V3H1V2H0V5H1V6H2V7H3V6H4V5H5V4H6V3H7V0Z' fill='%23808080'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
/*
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
select,
|
||||
textarea {
|
||||
padding: 3px 4px;
|
||||
border: none;
|
||||
box-shadow: var(--border-field);
|
||||
background-color: var(--Window);
|
||||
color: var(--WindowText);
|
||||
box-sizing: border-box;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
select {
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"] {
|
||||
/* For some reason descenders are getting cut off without this *.../
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
input[type="text"]:disabled,
|
||||
input[type="password"]:disabled,
|
||||
input[type="email"]:disabled,
|
||||
textarea:disabled {
|
||||
background-color: var(--surface);
|
||||
}
|
||||
|
||||
select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
position: relative;
|
||||
padding-right: 32px;
|
||||
background-image: svg-load("./icon/button-down.svg");
|
||||
background-position: top 2px right 2px;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
select:focus,
|
||||
input[type="text"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="email"]:focus,
|
||||
textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
*/
|
||||
|
||||
input[type="range"] {
|
||||
-webkit-appearance: none;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
input[type="range"]:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
height: 21px;
|
||||
width: 11px;
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='21' viewBox='0 0 11 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0V16H2V18H4V20H5V19H3V17H1V1H10V0Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M1 1V16H2V17H3V18H4V19H6V18H7V17H8V16H9V1Z' fill='%23C0C7C8'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 1H10V16H8V18H6V20H5V19H7V17H9Z' fill='%2387888F'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10 0H11V16H9V18H7V20H5V21H6V19H8V17H10Z' fill='black'/%3E %3C/svg%3E");
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
input[type="range"].has-box-indicator::-webkit-slider-thumb {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='21' viewBox='0 0 11 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0V20H1V1H10V0Z' fill='white'/%3E %3Crect x='1' y='1' width='8' height='18' fill='%23C0C7C8'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 1H10V20H1V19H9Z' fill='%2387888F'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10 0H11V21H0V20H10Z' fill='black'/%3E %3C/svg%3E");
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
height: 21px;
|
||||
width: 11px;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='21' viewBox='0 0 11 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0V16H2V18H4V20H5V19H3V17H1V1H10V0Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M1 1V16H2V17H3V18H4V19H6V18H7V17H8V16H9V1Z' fill='%23C0C7C8'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 1H10V16H8V18H6V20H5V19H7V17H9Z' fill='%2387888F'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10 0H11V16H9V18H7V20H5V21H6V19H8V17H10Z' fill='black'/%3E %3C/svg%3E");
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
input[type="range"].has-box-indicator::-moz-range-thumb {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='21' viewBox='0 0 11 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0V20H1V1H10V0Z' fill='white'/%3E %3Crect x='1' y='1' width='8' height='18' fill='%23C0C7C8'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 1H10V20H1V19H9Z' fill='%2387888F'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10 0H11V21H0V20H10Z' fill='black'/%3E %3C/svg%3E");
|
||||
transform: translateY(0px);
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
box-sizing: border-box;
|
||||
background: black;
|
||||
border-right: 1px solid grey;
|
||||
border-bottom: 1px solid grey;
|
||||
/* rtl:ignore */
|
||||
box-shadow: 1px 0 0 white, 1px 1px 0 white, 0 1px 0 white, -1px 0 0 darkgrey,
|
||||
-1px -1px 0 darkgrey, 0 -1px 0 darkgrey, -1px 1px 0 white, 1px -1px darkgrey;
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
box-sizing: border-box;
|
||||
background: black;
|
||||
border-right: 1px solid grey;
|
||||
border-bottom: 1px solid grey;
|
||||
/* rtl:ignore */
|
||||
box-shadow: 1px 0 0 white, 1px 1px 0 white, 0 1px 0 white, -1px 0 0 darkgrey,
|
||||
-1px -1px 0 darkgrey, 0 -1px 0 darkgrey, -1px 1px 0 white, 1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical {
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 150px;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"] {
|
||||
width: 150px;
|
||||
height: 4px;
|
||||
margin: 0 calc(var(--grouped-element-spacing) + var(--range-spacing)) 0
|
||||
var(--range-spacing);
|
||||
transform-origin: left;
|
||||
transform: rotate(270deg) translateX(calc(-50% + var(--element-spacing)));
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-webkit-slider-runnable-track {
|
||||
border-left: 1px solid grey;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid grey;
|
||||
/* rtl:ignore */
|
||||
box-shadow: -1px 0 0 white, -1px 1px 0 white, 0 1px 0 white, 1px 0 0 darkgrey,
|
||||
1px -1px 0 darkgrey, 0 -1px 0 darkgrey, 1px 1px 0 white, -1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-moz-range-track {
|
||||
border-left: 1px solid grey;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid grey;
|
||||
/* rtl:ignore */
|
||||
box-shadow: -1px 0 0 white, -1px 1px 0 white, 0 1px 0 white, 1px 0 0 darkgrey,
|
||||
1px -1px 0 darkgrey, 0 -1px 0 darkgrey, 1px 1px 0 white, -1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-webkit-slider-thumb {
|
||||
transform: translateY(-8px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"].has-box-indicator::-webkit-slider-thumb {
|
||||
transform: translateY(-10px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-moz-range-thumb {
|
||||
transform: translateY(2px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"].has-box-indicator::-moz-range-thumb {
|
||||
transform: translateY(0px) scaleX(-1);
|
||||
}
|
||||
|
||||
/* select:focus {
|
||||
color: var(--HilightText);
|
||||
background-color: var(--Hilight);
|
||||
}
|
||||
select:focus option {
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
select:active {
|
||||
background-image: svg-load("./icon/button-down-active.svg");
|
||||
} */
|
||||
|
||||
/* a {
|
||||
color: var(--link-blue);
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 1px dotted var(--link-blue);
|
||||
} */
|
||||
|
||||
/* ul.tree-view {
|
||||
display: block;
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
padding: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul.tree-view li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
ul.tree-view a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
ul.tree-view a:focus {
|
||||
background-color: var(--Hilight);
|
||||
color: var(--HilightText);
|
||||
}
|
||||
|
||||
ul.tree-view ul,
|
||||
ul.tree-view li {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
ul.tree-view ul {
|
||||
margin-left: 16px;
|
||||
padding-left: 16px;
|
||||
/* Goes down too far *.../
|
||||
border-left: 1px dotted #808080;
|
||||
}
|
||||
|
||||
ul.tree-view ul > li {
|
||||
position: relative;
|
||||
}
|
||||
ul.tree-view ul > li::before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -16px;
|
||||
top: 6px;
|
||||
width: 12px;
|
||||
border-bottom: 1px dotted #808080;
|
||||
}
|
||||
|
||||
/* Cover the bottom of the left dotted border *.../
|
||||
ul.tree-view ul > li:last-child::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -20px;
|
||||
top: 7px;
|
||||
bottom: 0px;
|
||||
width: 8px;
|
||||
background: var(--Window);
|
||||
}
|
||||
|
||||
ul.tree-view details {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ul.tree-view details[open] summary {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
ul.tree-view ul details > summary:before {
|
||||
margin-left: -22px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
ul.tree-view details > summary:before {
|
||||
text-align: center;
|
||||
display: block;
|
||||
float: left;
|
||||
content: "+";
|
||||
border: 1px solid #808080;
|
||||
width: 8px;
|
||||
height: 9px;
|
||||
line-height: 8px;
|
||||
margin-right: 5px;
|
||||
padding-left: 1px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
ul.tree-view details[open] > summary:before {
|
||||
content: "-";
|
||||
} */
|
||||
|
||||
/* pre {
|
||||
display: block;
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
padding: 12px 8px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
code,
|
||||
code * {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
summary:focus {
|
||||
outline: 1px dotted #000000;
|
||||
} */
|
||||
|
||||
/*
|
||||
::-webkit-scrollbar {
|
||||
width: 16px;
|
||||
}
|
||||
::-webkit-scrollbar:horizontal {
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: var(--button-face);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-image: svg-load("./icon/scrollbar-background.svg");
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--button-face);
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:horizontal:start:decrement,
|
||||
::-webkit-scrollbar-button:horizontal:end:increment,
|
||||
::-webkit-scrollbar-button:vertical:start:decrement,
|
||||
::-webkit-scrollbar-button:vertical:end:increment {
|
||||
display: block;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:vertical:start {
|
||||
height: 17px;
|
||||
background-image: svg-load("./icon/button-up.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:end {
|
||||
height: 17px;
|
||||
background-image: svg-load("./icon/button-down.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:start {
|
||||
width: 16px;
|
||||
background-image: svg-load("./icon/button-left.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:end {
|
||||
width: 16px;
|
||||
background-image: svg-load("./icon/button-right.svg");
|
||||
}
|
||||
*/
|
||||
|
||||
/*# sourceMappingURL=98.custom-build.css.map */
|
||||
1
static/html/jspaint/lib/98.css/98.custom-build.css.map
Normal file
1
static/html/jspaint/lib/98.css/98.custom-build.css.map
Normal file
File diff suppressed because one or more lines are too long
765
static/html/jspaint/lib/98.css/98.custom-build.rtl.css
Normal file
765
static/html/jspaint/lib/98.css/98.custom-build.rtl.css
Normal file
@@ -0,0 +1,765 @@
|
||||
/*! 98.css custom build - https://github.com/jdan/98.css */
|
||||
/**
|
||||
* 98.css
|
||||
* Copyright (c) 2020 Jordan Scales <thatjdanisso.cool>
|
||||
* https://github.com/jdan/98.css/blob/main/LICENSE
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Color */
|
||||
--surface: var(--ButtonFace, #c0c0c0);
|
||||
--button-highlight: var(--ButtonHilight, #ffffff);
|
||||
--button-face: var(--ButtonFace, #dfdfdf);
|
||||
--button-shadow: var(--ButtonShadow, #808080);
|
||||
--window-frame: var(--WindowFrame, #0a0a0a);
|
||||
--dialog-blue: var(--ActiveTitle, #000080);
|
||||
--dialog-blue-light: var(--GradientActiveTitle, #1084d0);
|
||||
--dialog-gray: var(--InactiveTitle, #808080);
|
||||
--dialog-gray-light: var(--GradientInactiveTitle, #b5b5b5);
|
||||
--link-blue: #0000ff;
|
||||
|
||||
/* Spacing */
|
||||
--element-spacing: 8px;
|
||||
--grouped-button-spacing: 4px;
|
||||
--grouped-element-spacing: 6px;
|
||||
--radio-width: 12px;
|
||||
--checkbox-width: 13px;
|
||||
--radio-label-spacing: 6px;
|
||||
--range-track-height: 4px;
|
||||
--range-spacing: 10px;
|
||||
|
||||
/* Some detailed computations for radio buttons and checkboxes */
|
||||
--radio-total-width-precalc: var(--radio-width) + var(--radio-label-spacing);
|
||||
--radio-total-width: calc(var(--radio-total-width-precalc));
|
||||
--radio-left: calc(-1 * var(--radio-total-width-precalc));
|
||||
--radio-dot-width: 4px;
|
||||
--radio-dot-top: calc(var(--radio-width) / 2 - var(--radio-dot-width) / 2);
|
||||
--radio-dot-left: calc(
|
||||
-1 * (var(--radio-total-width-precalc)) + var(--radio-width) / 2 - var(
|
||||
--radio-dot-width
|
||||
) / 2
|
||||
);
|
||||
|
||||
--checkbox-total-width-precalc: var(--checkbox-width) +
|
||||
var(--radio-label-spacing);
|
||||
--checkbox-total-width: calc(var(--checkbox-total-width-precalc));
|
||||
--checkbox-left: calc(-1 * var(--checkbox-total-width-precalc));
|
||||
--checkmark-width: 7px;
|
||||
--checkmark-top: 3px;
|
||||
--checkmark-left: 3px;
|
||||
|
||||
/* Borders */
|
||||
--border-width: 1px;
|
||||
--border-raised-outer: inset -1px -1px var(--window-frame),
|
||||
inset 1px 1px var(--button-highlight);
|
||||
--border-raised-inner: inset -2px -2px var(--button-shadow),
|
||||
inset 2px 2px var(--button-face);
|
||||
--border-sunken-outer: inset -1px -1px var(--button-highlight),
|
||||
inset 1px 1px var(--window-frame);
|
||||
--border-sunken-inner: inset -2px -2px var(--button-face),
|
||||
inset 2px 2px var(--button-shadow);
|
||||
|
||||
/* Window borders flip button-face and button-highlight */
|
||||
--border-window-outer: inset -1px -1px var(--window-frame),
|
||||
inset 1px 1px var(--button-face);
|
||||
--border-window-inner: inset -2px -2px var(--button-shadow),
|
||||
inset 2px 2px var(--button-highlight);
|
||||
|
||||
/* Field borders (checkbox, input, etc) flip window-frame and button-shadow */
|
||||
--border-field: inset -1px -1px var(--button-highlight),
|
||||
inset 1px 1px var(--button-shadow), inset -2px -2px var(--button-face),
|
||||
inset 2px 2px var(--window-frame);
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: "Pixelated MS Sans Serif";
|
||||
src: url("fonts/converted/ms_sans_serif.woff") format("woff");
|
||||
src: url("fonts/converted/ms_sans_serif.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Pixelated MS Sans Serif";
|
||||
src: url("fonts/converted/ms_sans_serif_bold.woff") format("woff");
|
||||
src: url("fonts/converted/ms_sans_serif_bold.woff2") format("woff2");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
button,
|
||||
label,
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
option,
|
||||
ul.tree-view,
|
||||
.window,
|
||||
.title-bar {
|
||||
font-family: "Pixelated MS Sans Serif", Arial;
|
||||
-webkit-font-smoothing: none;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
u {
|
||||
text-decoration: none;
|
||||
border-bottom: 0.5px solid #222222;
|
||||
}
|
||||
|
||||
button {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
background: var(--surface);
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
border-radius: 0;
|
||||
|
||||
min-width: 75px;
|
||||
min-height: 23px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.vertical-bar {
|
||||
width: 4px;
|
||||
height: 20px;
|
||||
background: #c0c0c0;
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
}
|
||||
|
||||
button:not(:disabled):active {
|
||||
box-shadow: var(--border-sunken-outer), var(--border-sunken-inner);
|
||||
padding: 2px 11px 0 13px;
|
||||
}
|
||||
|
||||
@media (not(hover)) {
|
||||
button:not(:disabled):hover {
|
||||
box-shadow: var(--border-sunken-outer), var(--border-sunken-inner);
|
||||
}
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px dotted #000000;
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
:disabled,
|
||||
:disabled + label {
|
||||
color: var(--button-shadow);
|
||||
}
|
||||
|
||||
button:disabled,
|
||||
:disabled + label {
|
||||
text-shadow: 1px 1px 0 var(--button-highlight);
|
||||
}
|
||||
|
||||
.window {
|
||||
box-shadow: var(--border-window-outer), var(--border-window-inner);
|
||||
background: var(--surface);
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--dialog-blue),
|
||||
var(--dialog-blue-light)
|
||||
);
|
||||
padding: 3px 2px 3px 3px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title-bar.inactive {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--dialog-gray),
|
||||
var(--dialog-gray-light)
|
||||
);
|
||||
}
|
||||
|
||||
.title-bar-text {
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
letter-spacing: 0;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.title-bar-controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title-bar-controls button {
|
||||
padding: 0;
|
||||
display: block;
|
||||
min-width: 16px;
|
||||
min-height: 14px;
|
||||
}
|
||||
|
||||
.title-bar-controls button:active {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.title-bar-controls button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Minimize"] {
|
||||
background-image: svg-load("./icon/minimize.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: bottom 3px left 4px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Maximize"] {
|
||||
background-image: svg-load("./icon/maximize.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 3px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Restore"] {
|
||||
background-image: svg-load("./icon/restore.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 3px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Help"] {
|
||||
background-image: svg-load("./icon/help.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 5px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Close"] {
|
||||
margin-left: 2px;
|
||||
background-image: svg-load("./icon/close.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 3px left 4px;
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
margin: 0px 1px;
|
||||
display: flex;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.status-bar-field {
|
||||
box-shadow: inset -1px -1px #dfdfdf,
|
||||
inset 1px 1px #808080;
|
||||
flex-grow: 1;
|
||||
padding: 2px 3px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.window-body {
|
||||
margin: var(--element-spacing);
|
||||
}
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg width='5' height='5' viewBox='0 0 5 5' fill='grey' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0H5V5H0V2H2V3H3V2H0' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0H4V4H0V1H1V3H3V1H0' fill='%23808080'/%3E %3C/svg%3E") 2;
|
||||
padding: calc(2 * var(--border-width) + var(--element-spacing));
|
||||
padding-block-start: var(--element-spacing);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
/* .field-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
[class^="field-row"] + [class^="field-row"] {
|
||||
margin-top: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row > * + * {
|
||||
margin-left: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row-stacked {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.field-row-stacked * + * {
|
||||
margin-top: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
} */
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
background: 100%;
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
input[type="radio"] + label,
|
||||
input[type="checkbox"] + label {
|
||||
line-height: 13px;
|
||||
}
|
||||
|
||||
input[type="radio"] + label {
|
||||
position: relative;
|
||||
margin-right: var(--radio-total-width);
|
||||
}
|
||||
|
||||
input[type="radio"] + label::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: calc(-1 * (var(--radio-total-width-precalc)));
|
||||
display: inline-block;
|
||||
width: var(--radio-width);
|
||||
height: var(--radio-width);
|
||||
margin-left: var(--radio-label-spacing);
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 0H4V1H2V2H1V4H0V8H1V10H2V8H1V4H2V2H4V1H8V2H10V1H8V0Z' fill='%23808080'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 1H4V2H2V3V4H1V8H2V9H3V8H2V4H3V3H4V2H8V3H10V2H8V1Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 3H10V4H9V3ZM10 8V4H11V8H10ZM8 10V9H9V8H10V9V10H8ZM4 10V11H8V10H4ZM4 10V9H2V10H4Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 2H10V4H11V8H10V10H8V11H4V10H2V11H4V12H8V11H10V10H11V8H12V4H11V2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2H8V3H9V4H10V8H9V9H8V10H4V9H3V8H2V4H3V3H4V2Z' fill='white'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="radio"]:active + label::before {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 0H4V1H2V2H1V4H0V8H1V10H2V8H1V4H2V2H4V1H8V2H10V1H8V0Z' fill='%23808080'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 1H4V2H2V3V4H1V8H2V9H3V8H2V4H3V3H4V2H8V3H10V2H8V1Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 3H10V4H9V3ZM10 8V4H11V8H10ZM8 10V9H9V8H10V9V10H8ZM4 10V11H8V10H4ZM4 10V9H2V10H4Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 2H10V4H11V8H10V10H8V11H4V10H2V11H4V12H8V11H10V10H11V8H12V4H11V2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2H8V3H9V4H10V8H9V9H8V10H4V9H3V8H2V4H3V3H4V2Z' fill='%23C0C0C0'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="radio"]:checked + label::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: var(--radio-dot-width);
|
||||
height: var(--radio-dot-width);
|
||||
top: var(--radio-dot-top);
|
||||
right: var(--radio-dot-left);
|
||||
position: absolute;
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='4' height='4' viewBox='0 0 4 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M3 0H1V1H0V2V3H1V4H3V3H4V2V1H3V0Z' fill='black'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="radio"]:focus + label,
|
||||
input[type="checkbox"]:focus + label {
|
||||
outline: 1px dotted #000000;
|
||||
}
|
||||
|
||||
input[type="radio"][disabled] + label::before {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 0H4V1H2V2H1V4H0V8H1V10H2V8H1V4H2V2H4V1H8V2H10V1H8V0Z' fill='%23808080'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8 1H4V2H2V3V4H1V8H2V9H3V8H2V4H3V3H4V2H8V3H10V2H8V1Z' fill='black'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 3H10V4H9V3ZM10 8V4H11V8H10ZM8 10V9H9V8H10V9V10H8ZM4 10V11H8V10H4ZM4 10V9H2V10H4Z' fill='%23DFDFDF'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 2H10V4H11V8H10V10H8V11H4V10H2V11H4V12H8V11H10V10H11V8H12V4H11V2Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4 2H8V3H9V4H10V8H9V9H8V10H4V9H3V8H2V4H3V3H4V2Z' fill='%23C0C0C0'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="radio"][disabled]:checked + label::after {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='4' height='4' viewBox='0 0 4 4' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M3 0H1V1H0V2V3H1V4H3V3H4V2V1H3V0Z' fill='%23808080'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="checkbox"] + label {
|
||||
position: relative;
|
||||
margin-right: var(--checkbox-total-width);
|
||||
}
|
||||
|
||||
input[type="checkbox"] + label::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: calc(-1 * (var(--checkbox-total-width-precalc)));
|
||||
display: inline-block;
|
||||
width: var(--checkbox-width);
|
||||
height: var(--checkbox-width);
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
margin-left: var(--radio-label-spacing);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:active + label::before {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked + label::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: var(--checkmark-width);
|
||||
height: var(--checkmark-width);
|
||||
position: absolute;
|
||||
top: var(--checkmark-top);
|
||||
right: calc(
|
||||
-1 * (var(--checkbox-total-width-precalc)) + var(--checkmark-left)
|
||||
);
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='7' height='7' viewBox='0 0 7 7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 0H6V1H5V2H4V3H3V4H2V3H1V2H0V5H1V6H2V7H3V6H4V5H5V4H6V3H7V0Z' fill='black'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
input[type="checkbox"][disabled] + label::before {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
input[type="checkbox"][disabled]:checked + label::after {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='7' height='7' viewBox='0 0 7 7' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M7 0H6V1H5V2H4V3H3V4H2V3H1V2H0V5H1V6H2V7H3V6H4V5H5V4H6V3H7V0Z' fill='%23808080'/%3E %3C/svg%3E");
|
||||
}
|
||||
|
||||
/*
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
select,
|
||||
textarea {
|
||||
padding: 3px 4px;
|
||||
border: none;
|
||||
box-shadow: var(--border-field);
|
||||
background-color: var(--Window);
|
||||
color: var(--WindowText);
|
||||
box-sizing: border-box;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
select {
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"] {
|
||||
/* For some reason descenders are getting cut off without this *.../
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
input[type="text"]:disabled,
|
||||
input[type="password"]:disabled,
|
||||
input[type="email"]:disabled,
|
||||
textarea:disabled {
|
||||
background-color: var(--surface);
|
||||
}
|
||||
|
||||
select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
position: relative;
|
||||
padding-right: 32px;
|
||||
background-image: svg-load("./icon/button-down.svg");
|
||||
background-position: top 2px right 2px;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
select:focus,
|
||||
input[type="text"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="email"]:focus,
|
||||
textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
*/
|
||||
|
||||
input[type="range"] {
|
||||
-webkit-appearance: none;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
input[type="range"]:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
height: 21px;
|
||||
width: 11px;
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='21' viewBox='0 0 11 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0V16H2V18H4V20H5V19H3V17H1V1H10V0Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M1 1V16H2V17H3V18H4V19H6V18H7V17H8V16H9V1Z' fill='%23C0C7C8'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 1H10V16H8V18H6V20H5V19H7V17H9Z' fill='%2387888F'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10 0H11V16H9V18H7V20H5V21H6V19H8V17H10Z' fill='black'/%3E %3C/svg%3E");
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
input[type="range"].has-box-indicator::-webkit-slider-thumb {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='21' viewBox='0 0 11 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0V20H1V1H10V0Z' fill='white'/%3E %3Crect x='1' y='1' width='8' height='18' fill='%23C0C7C8'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 1H10V20H1V19H9Z' fill='%2387888F'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10 0H11V21H0V20H10Z' fill='black'/%3E %3C/svg%3E");
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
height: 21px;
|
||||
width: 11px;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='21' viewBox='0 0 11 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0V16H2V18H4V20H5V19H3V17H1V1H10V0Z' fill='white'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M1 1V16H2V17H3V18H4V19H6V18H7V17H8V16H9V1Z' fill='%23C0C7C8'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 1H10V16H8V18H6V20H5V19H7V17H9Z' fill='%2387888F'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10 0H11V16H9V18H7V20H5V21H6V19H8V17H10Z' fill='black'/%3E %3C/svg%3E");
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
input[type="range"].has-box-indicator::-moz-range-thumb {
|
||||
background: url("data:image/svg+xml;charset=utf-8,%3Csvg width='11' height='21' viewBox='0 0 11 21' fill='none' xmlns='http://www.w3.org/2000/svg'%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M0 0V20H1V1H10V0Z' fill='white'/%3E %3Crect x='1' y='1' width='8' height='18' fill='%23C0C7C8'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9 1H10V20H1V19H9Z' fill='%2387888F'/%3E %3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10 0H11V21H0V20H10Z' fill='black'/%3E %3C/svg%3E");
|
||||
transform: translateY(0px);
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
box-sizing: border-box;
|
||||
background: black;
|
||||
border-left: 1px solid grey;
|
||||
border-bottom: 1px solid grey;
|
||||
box-shadow: 1px 0 0 white, 1px 1px 0 white, 0 1px 0 white, -1px 0 0 darkgrey,
|
||||
-1px -1px 0 darkgrey, 0 -1px 0 darkgrey, -1px 1px 0 white, 1px -1px darkgrey;
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
box-sizing: border-box;
|
||||
background: black;
|
||||
border-left: 1px solid grey;
|
||||
border-bottom: 1px solid grey;
|
||||
box-shadow: 1px 0 0 white, 1px 1px 0 white, 0 1px 0 white, -1px 0 0 darkgrey,
|
||||
-1px -1px 0 darkgrey, 0 -1px 0 darkgrey, -1px 1px 0 white, 1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical {
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 150px;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"] {
|
||||
width: 150px;
|
||||
height: 4px;
|
||||
margin: 0 var(--range-spacing) 0
|
||||
calc(var(--grouped-element-spacing) + var(--range-spacing));
|
||||
transform-origin: right;
|
||||
transform: rotate(-270deg) translateX(calc(-1*(-50% + var(--element-spacing))));
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-webkit-slider-runnable-track {
|
||||
border-right: 1px solid grey;
|
||||
border-left: 0;
|
||||
border-bottom: 1px solid grey;
|
||||
box-shadow: -1px 0 0 white, -1px 1px 0 white, 0 1px 0 white, 1px 0 0 darkgrey,
|
||||
1px -1px 0 darkgrey, 0 -1px 0 darkgrey, 1px 1px 0 white, -1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-moz-range-track {
|
||||
border-right: 1px solid grey;
|
||||
border-left: 0;
|
||||
border-bottom: 1px solid grey;
|
||||
box-shadow: -1px 0 0 white, -1px 1px 0 white, 0 1px 0 white, 1px 0 0 darkgrey,
|
||||
1px -1px 0 darkgrey, 0 -1px 0 darkgrey, 1px 1px 0 white, -1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-webkit-slider-thumb {
|
||||
transform: translateY(-8px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"].has-box-indicator::-webkit-slider-thumb {
|
||||
transform: translateY(-10px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-moz-range-thumb {
|
||||
transform: translateY(2px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"].has-box-indicator::-moz-range-thumb {
|
||||
transform: translateY(0px) scaleX(-1);
|
||||
}
|
||||
|
||||
/* select:focus {
|
||||
color: var(--HilightText);
|
||||
background-color: var(--Hilight);
|
||||
}
|
||||
select:focus option {
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
select:active {
|
||||
background-image: svg-load("./icon/button-down-active.svg");
|
||||
} */
|
||||
|
||||
/* a {
|
||||
color: var(--link-blue);
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 1px dotted var(--link-blue);
|
||||
} */
|
||||
|
||||
/* ul.tree-view {
|
||||
display: block;
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
padding: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul.tree-view li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
ul.tree-view a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
ul.tree-view a:focus {
|
||||
background-color: var(--Hilight);
|
||||
color: var(--HilightText);
|
||||
}
|
||||
|
||||
ul.tree-view ul,
|
||||
ul.tree-view li {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
ul.tree-view ul {
|
||||
margin-left: 16px;
|
||||
padding-left: 16px;
|
||||
/* Goes down too far *.../
|
||||
border-left: 1px dotted #808080;
|
||||
}
|
||||
|
||||
ul.tree-view ul > li {
|
||||
position: relative;
|
||||
}
|
||||
ul.tree-view ul > li::before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -16px;
|
||||
top: 6px;
|
||||
width: 12px;
|
||||
border-bottom: 1px dotted #808080;
|
||||
}
|
||||
|
||||
/* Cover the bottom of the left dotted border *.../
|
||||
ul.tree-view ul > li:last-child::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -20px;
|
||||
top: 7px;
|
||||
bottom: 0px;
|
||||
width: 8px;
|
||||
background: var(--Window);
|
||||
}
|
||||
|
||||
ul.tree-view details {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ul.tree-view details[open] summary {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
ul.tree-view ul details > summary:before {
|
||||
margin-left: -22px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
ul.tree-view details > summary:before {
|
||||
text-align: center;
|
||||
display: block;
|
||||
float: left;
|
||||
content: "+";
|
||||
border: 1px solid #808080;
|
||||
width: 8px;
|
||||
height: 9px;
|
||||
line-height: 8px;
|
||||
margin-right: 5px;
|
||||
padding-left: 1px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
ul.tree-view details[open] > summary:before {
|
||||
content: "-";
|
||||
} */
|
||||
|
||||
/* pre {
|
||||
display: block;
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
padding: 12px 8px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
code,
|
||||
code * {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
summary:focus {
|
||||
outline: 1px dotted #000000;
|
||||
} */
|
||||
|
||||
/*
|
||||
::-webkit-scrollbar {
|
||||
width: 16px;
|
||||
}
|
||||
::-webkit-scrollbar:horizontal {
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: var(--button-face);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-image: svg-load("./icon/scrollbar-background.svg");
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--button-face);
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:horizontal:start:decrement,
|
||||
::-webkit-scrollbar-button:horizontal:end:increment,
|
||||
::-webkit-scrollbar-button:vertical:start:decrement,
|
||||
::-webkit-scrollbar-button:vertical:end:increment {
|
||||
display: block;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:vertical:start {
|
||||
height: 17px;
|
||||
background-image: svg-load("./icon/button-up.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:end {
|
||||
height: 17px;
|
||||
background-image: svg-load("./icon/button-down.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:start {
|
||||
width: 16px;
|
||||
background-image: svg-load("./icon/button-left.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:end {
|
||||
width: 16px;
|
||||
background-image: svg-load("./icon/button-right.svg");
|
||||
}
|
||||
*/
|
||||
775
static/html/jspaint/lib/98.css/98.custom-src.css
Normal file
775
static/html/jspaint/lib/98.css/98.custom-src.css
Normal file
@@ -0,0 +1,775 @@
|
||||
/**
|
||||
* 98.css
|
||||
* Copyright (c) 2020 Jordan Scales <thatjdanisso.cool>
|
||||
* https://github.com/jdan/98.css/blob/main/LICENSE
|
||||
*/
|
||||
|
||||
:root {
|
||||
/* Color */
|
||||
--surface: var(--ButtonFace, #c0c0c0);
|
||||
--button-highlight: var(--ButtonHilight, #ffffff);
|
||||
--button-face: var(--ButtonFace, #dfdfdf);
|
||||
--button-shadow: var(--ButtonShadow, #808080);
|
||||
--window-frame: var(--WindowFrame, #0a0a0a);
|
||||
--dialog-blue: var(--ActiveTitle, #000080);
|
||||
--dialog-blue-light: var(--GradientActiveTitle, #1084d0);
|
||||
--dialog-gray: var(--InactiveTitle, #808080);
|
||||
--dialog-gray-light: var(--GradientInactiveTitle, #b5b5b5);
|
||||
--link-blue: #0000ff;
|
||||
|
||||
/* Spacing */
|
||||
--element-spacing: 8px;
|
||||
--grouped-button-spacing: 4px;
|
||||
--grouped-element-spacing: 6px;
|
||||
--radio-width: 12px;
|
||||
--checkbox-width: 13px;
|
||||
--radio-label-spacing: 6px;
|
||||
--range-track-height: 4px;
|
||||
--range-spacing: 10px;
|
||||
|
||||
/* Some detailed computations for radio buttons and checkboxes */
|
||||
--radio-total-width-precalc: var(--radio-width) + var(--radio-label-spacing);
|
||||
--radio-total-width: calc(var(--radio-total-width-precalc));
|
||||
--radio-left: calc(-1 * var(--radio-total-width-precalc));
|
||||
--radio-dot-width: 4px;
|
||||
--radio-dot-top: calc(var(--radio-width) / 2 - var(--radio-dot-width) / 2);
|
||||
--radio-dot-left: calc(
|
||||
-1 * (var(--radio-total-width-precalc)) + var(--radio-width) / 2 - var(
|
||||
--radio-dot-width
|
||||
) / 2
|
||||
);
|
||||
|
||||
--checkbox-total-width-precalc: var(--checkbox-width) +
|
||||
var(--radio-label-spacing);
|
||||
--checkbox-total-width: calc(var(--checkbox-total-width-precalc));
|
||||
--checkbox-left: calc(-1 * var(--checkbox-total-width-precalc));
|
||||
--checkmark-width: 7px;
|
||||
--checkmark-top: 3px;
|
||||
--checkmark-left: 3px;
|
||||
|
||||
/* Borders */
|
||||
--border-width: 1px;
|
||||
/* rtl:ignore */
|
||||
--border-raised-outer: inset -1px -1px var(--window-frame),
|
||||
inset 1px 1px var(--button-highlight);
|
||||
/* rtl:ignore */
|
||||
--border-raised-inner: inset -2px -2px var(--button-shadow),
|
||||
inset 2px 2px var(--button-face);
|
||||
/* rtl:ignore */
|
||||
--border-sunken-outer: inset -1px -1px var(--button-highlight),
|
||||
inset 1px 1px var(--window-frame);
|
||||
/* rtl:ignore */
|
||||
--border-sunken-inner: inset -2px -2px var(--button-face),
|
||||
inset 2px 2px var(--button-shadow);
|
||||
|
||||
/* Window borders flip button-face and button-highlight */
|
||||
/* rtl:ignore */
|
||||
--border-window-outer: inset -1px -1px var(--window-frame),
|
||||
inset 1px 1px var(--button-face);
|
||||
/* rtl:ignore */
|
||||
--border-window-inner: inset -2px -2px var(--button-shadow),
|
||||
inset 2px 2px var(--button-highlight);
|
||||
|
||||
/* Field borders (checkbox, input, etc) flip window-frame and button-shadow */
|
||||
/* rtl:ignore */
|
||||
--border-field: inset -1px -1px var(--button-highlight),
|
||||
inset 1px 1px var(--button-shadow), inset -2px -2px var(--button-face),
|
||||
inset 2px 2px var(--window-frame);
|
||||
}
|
||||
|
||||
/*
|
||||
@font-face {
|
||||
font-family: "Pixelated MS Sans Serif";
|
||||
src: url("fonts/converted/ms_sans_serif.woff") format("woff");
|
||||
src: url("fonts/converted/ms_sans_serif.woff2") format("woff2");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Pixelated MS Sans Serif";
|
||||
src: url("fonts/converted/ms_sans_serif_bold.woff") format("woff");
|
||||
src: url("fonts/converted/ms_sans_serif_bold.woff2") format("woff2");
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial;
|
||||
font-size: 12px;
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
button,
|
||||
label,
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
option,
|
||||
ul.tree-view,
|
||||
.window,
|
||||
.title-bar {
|
||||
font-family: "Pixelated MS Sans Serif", Arial;
|
||||
-webkit-font-smoothing: none;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
u {
|
||||
text-decoration: none;
|
||||
border-bottom: 0.5px solid #222222;
|
||||
}
|
||||
|
||||
button {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
background: var(--surface);
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
border-radius: 0;
|
||||
|
||||
min-width: 75px;
|
||||
min-height: 23px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
.vertical-bar {
|
||||
width: 4px;
|
||||
height: 20px;
|
||||
background: #c0c0c0;
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
}
|
||||
|
||||
button:not(:disabled):active {
|
||||
box-shadow: var(--border-sunken-outer), var(--border-sunken-inner);
|
||||
padding: 2px 11px 0 13px;
|
||||
}
|
||||
|
||||
@media (not(hover)) {
|
||||
button:not(:disabled):hover {
|
||||
box-shadow: var(--border-sunken-outer), var(--border-sunken-inner);
|
||||
}
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px dotted #000000;
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
button::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
:disabled,
|
||||
:disabled + label {
|
||||
color: var(--button-shadow);
|
||||
}
|
||||
|
||||
button:disabled,
|
||||
:disabled + label {
|
||||
text-shadow: 1px 1px 0 var(--button-highlight);
|
||||
}
|
||||
|
||||
.window {
|
||||
box-shadow: var(--border-window-outer), var(--border-window-inner);
|
||||
background: var(--surface);
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--dialog-blue),
|
||||
var(--dialog-blue-light)
|
||||
);
|
||||
padding: 3px 2px 3px 3px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title-bar.inactive {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--dialog-gray),
|
||||
var(--dialog-gray-light)
|
||||
);
|
||||
}
|
||||
|
||||
.title-bar-text {
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
letter-spacing: 0;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.title-bar-controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title-bar-controls button {
|
||||
padding: 0;
|
||||
display: block;
|
||||
min-width: 16px;
|
||||
min-height: 14px;
|
||||
}
|
||||
|
||||
.title-bar-controls button:active {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.title-bar-controls button:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Minimize"] {
|
||||
background-image: svg-load("./icon/minimize.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: bottom 3px left 4px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Maximize"] {
|
||||
background-image: svg-load("./icon/maximize.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 3px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Restore"] {
|
||||
background-image: svg-load("./icon/restore.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 3px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Help"] {
|
||||
background-image: svg-load("./icon/help.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 2px left 5px;
|
||||
}
|
||||
|
||||
.title-bar-controls button[aria-label="Close"] {
|
||||
margin-left: 2px;
|
||||
background-image: svg-load("./icon/close.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: top 3px left 4px;
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
margin: 0px 1px;
|
||||
display: flex;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.status-bar-field {
|
||||
box-shadow: inset -1px -1px #dfdfdf,
|
||||
inset 1px 1px #808080;
|
||||
flex-grow: 1;
|
||||
padding: 2px 3px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.window-body {
|
||||
margin: var(--element-spacing);
|
||||
}
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border-image: svg-load("./icon/groupbox-border.svg") 2;
|
||||
padding: calc(2 * var(--border-width) + var(--element-spacing));
|
||||
padding-block-start: var(--element-spacing);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
/* .field-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
[class^="field-row"] + [class^="field-row"] {
|
||||
margin-top: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row > * + * {
|
||||
margin-left: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row-stacked {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.field-row-stacked * + * {
|
||||
margin-top: var(--grouped-element-spacing);
|
||||
}
|
||||
|
||||
.field-row label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
} */
|
||||
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
background: 0;
|
||||
position: fixed;
|
||||
opacity: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
input[type="radio"] + label,
|
||||
input[type="checkbox"] + label {
|
||||
line-height: 13px;
|
||||
}
|
||||
|
||||
input[type="radio"] + label {
|
||||
position: relative;
|
||||
margin-left: var(--radio-total-width);
|
||||
}
|
||||
|
||||
input[type="radio"] + label::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: calc(-1 * (var(--radio-total-width-precalc)));
|
||||
display: inline-block;
|
||||
width: var(--radio-width);
|
||||
height: var(--radio-width);
|
||||
margin-right: var(--radio-label-spacing);
|
||||
background: svg-load("./icon/radio-border.svg");
|
||||
}
|
||||
|
||||
input[type="radio"]:active + label::before {
|
||||
background: svg-load("./icon/radio-border-disabled.svg");
|
||||
}
|
||||
|
||||
input[type="radio"]:checked + label::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: var(--radio-dot-width);
|
||||
height: var(--radio-dot-width);
|
||||
top: var(--radio-dot-top);
|
||||
left: var(--radio-dot-left);
|
||||
position: absolute;
|
||||
background: svg-load("./icon/radio-dot.svg");
|
||||
}
|
||||
|
||||
input[type="radio"]:focus + label,
|
||||
input[type="checkbox"]:focus + label {
|
||||
outline: 1px dotted #000000;
|
||||
}
|
||||
|
||||
input[type="radio"][disabled] + label::before {
|
||||
background: svg-load("./icon/radio-border-disabled.svg");
|
||||
}
|
||||
|
||||
input[type="radio"][disabled]:checked + label::after {
|
||||
background: svg-load("./icon/radio-dot-disabled.svg");
|
||||
}
|
||||
|
||||
input[type="checkbox"] + label {
|
||||
position: relative;
|
||||
margin-left: var(--checkbox-total-width);
|
||||
}
|
||||
|
||||
input[type="checkbox"] + label::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: calc(-1 * (var(--checkbox-total-width-precalc)));
|
||||
display: inline-block;
|
||||
width: var(--checkbox-width);
|
||||
height: var(--checkbox-width);
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
margin-right: var(--radio-label-spacing);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:active + label::before {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked + label::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: var(--checkmark-width);
|
||||
height: var(--checkmark-width);
|
||||
position: absolute;
|
||||
top: var(--checkmark-top);
|
||||
left: calc(
|
||||
-1 * (var(--checkbox-total-width-precalc)) + var(--checkmark-left)
|
||||
);
|
||||
background: svg-load("./icon/checkmark.svg");
|
||||
}
|
||||
|
||||
input[type="checkbox"][disabled] + label::before {
|
||||
background: var(--surface);
|
||||
}
|
||||
|
||||
input[type="checkbox"][disabled]:checked + label::after {
|
||||
background: svg-load("./icon/checkmark-disabled.svg");
|
||||
}
|
||||
|
||||
/*
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
select,
|
||||
textarea {
|
||||
padding: 3px 4px;
|
||||
border: none;
|
||||
box-shadow: var(--border-field);
|
||||
background-color: var(--Window);
|
||||
color: var(--WindowText);
|
||||
box-sizing: border-box;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"],
|
||||
select {
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"] {
|
||||
/* For some reason descenders are getting cut off without this *.../
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
input[type="text"]:disabled,
|
||||
input[type="password"]:disabled,
|
||||
input[type="email"]:disabled,
|
||||
textarea:disabled {
|
||||
background-color: var(--surface);
|
||||
}
|
||||
|
||||
select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
position: relative;
|
||||
padding-right: 32px;
|
||||
background-image: svg-load("./icon/button-down.svg");
|
||||
background-position: top 2px right 2px;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
select:focus,
|
||||
input[type="text"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="email"]:focus,
|
||||
textarea:focus {
|
||||
outline: none;
|
||||
}
|
||||
*/
|
||||
|
||||
input[type="range"] {
|
||||
-webkit-appearance: none;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
input[type="range"]:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
height: 21px;
|
||||
width: 11px;
|
||||
background: svg-load("./icon/indicator-horizontal.svg");
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
input[type="range"].has-box-indicator::-webkit-slider-thumb {
|
||||
background: svg-load("./icon/indicator-rectangle-horizontal.svg");
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-thumb {
|
||||
height: 21px;
|
||||
width: 11px;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
background: svg-load("./icon/indicator-horizontal.svg");
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
input[type="range"].has-box-indicator::-moz-range-thumb {
|
||||
background: svg-load("./icon/indicator-rectangle-horizontal.svg");
|
||||
transform: translateY(0px);
|
||||
}
|
||||
|
||||
input[type="range"]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
box-sizing: border-box;
|
||||
background: black;
|
||||
border-right: 1px solid grey;
|
||||
border-bottom: 1px solid grey;
|
||||
/* rtl:ignore */
|
||||
box-shadow: 1px 0 0 white, 1px 1px 0 white, 0 1px 0 white, -1px 0 0 darkgrey,
|
||||
-1px -1px 0 darkgrey, 0 -1px 0 darkgrey, -1px 1px 0 white, 1px -1px darkgrey;
|
||||
}
|
||||
|
||||
input[type="range"]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
box-sizing: border-box;
|
||||
background: black;
|
||||
border-right: 1px solid grey;
|
||||
border-bottom: 1px solid grey;
|
||||
/* rtl:ignore */
|
||||
box-shadow: 1px 0 0 white, 1px 1px 0 white, 0 1px 0 white, -1px 0 0 darkgrey,
|
||||
-1px -1px 0 darkgrey, 0 -1px 0 darkgrey, -1px 1px 0 white, 1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical {
|
||||
display: inline-block;
|
||||
width: 4px;
|
||||
height: 150px;
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"] {
|
||||
width: 150px;
|
||||
height: 4px;
|
||||
margin: 0 calc(var(--grouped-element-spacing) + var(--range-spacing)) 0
|
||||
var(--range-spacing);
|
||||
transform-origin: left;
|
||||
transform: rotate(270deg) translateX(calc(-50% + var(--element-spacing)));
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-webkit-slider-runnable-track {
|
||||
border-left: 1px solid grey;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid grey;
|
||||
/* rtl:ignore */
|
||||
box-shadow: -1px 0 0 white, -1px 1px 0 white, 0 1px 0 white, 1px 0 0 darkgrey,
|
||||
1px -1px 0 darkgrey, 0 -1px 0 darkgrey, 1px 1px 0 white, -1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-moz-range-track {
|
||||
border-left: 1px solid grey;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid grey;
|
||||
/* rtl:ignore */
|
||||
box-shadow: -1px 0 0 white, -1px 1px 0 white, 0 1px 0 white, 1px 0 0 darkgrey,
|
||||
1px -1px 0 darkgrey, 0 -1px 0 darkgrey, 1px 1px 0 white, -1px -1px darkgrey;
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-webkit-slider-thumb {
|
||||
transform: translateY(-8px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"].has-box-indicator::-webkit-slider-thumb {
|
||||
transform: translateY(-10px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"]::-moz-range-thumb {
|
||||
transform: translateY(2px) scaleX(-1);
|
||||
}
|
||||
|
||||
.is-vertical > input[type="range"].has-box-indicator::-moz-range-thumb {
|
||||
transform: translateY(0px) scaleX(-1);
|
||||
}
|
||||
|
||||
/* select:focus {
|
||||
color: var(--HilightText);
|
||||
background-color: var(--Hilight);
|
||||
}
|
||||
select:focus option {
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
select:active {
|
||||
background-image: svg-load("./icon/button-down-active.svg");
|
||||
} */
|
||||
|
||||
/* a {
|
||||
color: var(--link-blue);
|
||||
}
|
||||
|
||||
a:focus {
|
||||
outline: 1px dotted var(--link-blue);
|
||||
} */
|
||||
|
||||
/* ul.tree-view {
|
||||
display: block;
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
padding: 6px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul.tree-view li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
ul.tree-view a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
ul.tree-view a:focus {
|
||||
background-color: var(--Hilight);
|
||||
color: var(--HilightText);
|
||||
}
|
||||
|
||||
ul.tree-view ul,
|
||||
ul.tree-view li {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
ul.tree-view ul {
|
||||
margin-left: 16px;
|
||||
padding-left: 16px;
|
||||
/* Goes down too far *.../
|
||||
border-left: 1px dotted #808080;
|
||||
}
|
||||
|
||||
ul.tree-view ul > li {
|
||||
position: relative;
|
||||
}
|
||||
ul.tree-view ul > li::before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -16px;
|
||||
top: 6px;
|
||||
width: 12px;
|
||||
border-bottom: 1px dotted #808080;
|
||||
}
|
||||
|
||||
/* Cover the bottom of the left dotted border *.../
|
||||
ul.tree-view ul > li:last-child::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -20px;
|
||||
top: 7px;
|
||||
bottom: 0px;
|
||||
width: 8px;
|
||||
background: var(--Window);
|
||||
}
|
||||
|
||||
ul.tree-view details {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ul.tree-view details[open] summary {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
ul.tree-view ul details > summary:before {
|
||||
margin-left: -22px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
ul.tree-view details > summary:before {
|
||||
text-align: center;
|
||||
display: block;
|
||||
float: left;
|
||||
content: "+";
|
||||
border: 1px solid #808080;
|
||||
width: 8px;
|
||||
height: 9px;
|
||||
line-height: 8px;
|
||||
margin-right: 5px;
|
||||
padding-left: 1px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
ul.tree-view details[open] > summary:before {
|
||||
content: "-";
|
||||
} */
|
||||
|
||||
/* pre {
|
||||
display: block;
|
||||
background: var(--Window);
|
||||
box-shadow: var(--border-field);
|
||||
padding: 12px 8px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
code,
|
||||
code * {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
summary:focus {
|
||||
outline: 1px dotted #000000;
|
||||
} */
|
||||
|
||||
/*
|
||||
::-webkit-scrollbar {
|
||||
width: 16px;
|
||||
}
|
||||
::-webkit-scrollbar:horizontal {
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: var(--button-face);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-image: svg-load("./icon/scrollbar-background.svg");
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--button-face);
|
||||
box-shadow: var(--border-raised-outer), var(--border-raised-inner);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:horizontal:start:decrement,
|
||||
::-webkit-scrollbar-button:horizontal:end:increment,
|
||||
::-webkit-scrollbar-button:vertical:start:decrement,
|
||||
::-webkit-scrollbar-button:vertical:end:increment {
|
||||
display: block;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:vertical:start {
|
||||
height: 17px;
|
||||
background-image: svg-load("./icon/button-up.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:end {
|
||||
height: 17px;
|
||||
background-image: svg-load("./icon/button-down.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:start {
|
||||
width: 16px;
|
||||
background-image: svg-load("./icon/button-left.svg");
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:end {
|
||||
width: 16px;
|
||||
background-image: svg-load("./icon/button-right.svg");
|
||||
}
|
||||
*/
|
||||
81
static/html/jspaint/lib/98.css/modified-build.js
Normal file
81
static/html/jspaint/lib/98.css/modified-build.js
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env node
|
||||
const dedent = require("dedent");
|
||||
const ejs = require("ejs");
|
||||
const fs = require("fs");
|
||||
const glob = require("glob");
|
||||
const hljs = require("highlight.js");
|
||||
const mkdirp = require("mkdirp");
|
||||
const path = require("path");
|
||||
const postcss = require("postcss");
|
||||
|
||||
const { homepage, version } = require("./package.json");
|
||||
|
||||
function buildCSS() {
|
||||
const input =
|
||||
`/*! 98.css custom build - ${homepage} */\n` + fs.readFileSync("style.css");
|
||||
|
||||
return postcss()
|
||||
.use(require("postcss-inline-svg"))
|
||||
// .use(require("postcss-css-variables"))
|
||||
// .use(require("postcss-calc"))
|
||||
.use(require("postcss-copy")({ dest: "dist", template: "[name].[ext]" }))
|
||||
// .use(require("cssnano"))
|
||||
.process(input, {
|
||||
from: "style.css",
|
||||
to: "dist/98.custom-build.css",
|
||||
map: { inline: false },
|
||||
})
|
||||
.then((result) => {
|
||||
mkdirp.sync("dist");
|
||||
fs.writeFileSync("dist/98.custom-build.css", result.css);
|
||||
fs.writeFileSync("dist/98.custom-build.css.map", result.map.toString());
|
||||
});
|
||||
}
|
||||
|
||||
function buildDocs() {
|
||||
let id = 0;
|
||||
function getNewId() {
|
||||
return ++id;
|
||||
}
|
||||
function getCurrentId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
const template = fs.readFileSync("docs/index.html.ejs", "utf-8");
|
||||
function example(code) {
|
||||
const magicBrackets = /\[\[(.*)\]\]/g;
|
||||
const dedented = dedent(code);
|
||||
const inline = dedented.replace(magicBrackets, "$1");
|
||||
const escaped = hljs.highlight("html", dedented.replace(magicBrackets, ""))
|
||||
.value;
|
||||
|
||||
return `<div class="example">
|
||||
${inline}
|
||||
<details>
|
||||
<summary>Show code</summary>
|
||||
<pre><code>${escaped}</code></pre>
|
||||
</details>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
glob("docs/*", (err, files) => {
|
||||
if (!err) {
|
||||
files.forEach((srcFile) =>
|
||||
fs.copyFileSync(srcFile, path.join("dist", path.basename(srcFile)))
|
||||
);
|
||||
} else throw "error globbing dist directory.";
|
||||
});
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "/dist/index.html"),
|
||||
ejs.render(template, { getNewId, getCurrentId, example })
|
||||
);
|
||||
}
|
||||
|
||||
function build() {
|
||||
buildCSS()
|
||||
.then(buildDocs)
|
||||
.catch((err) => console.log(err));
|
||||
}
|
||||
module.exports = build;
|
||||
|
||||
build();
|
||||
188
static/html/jspaint/lib/FileSaver.js
Normal file
188
static/html/jspaint/lib/FileSaver.js
Normal file
@@ -0,0 +1,188 @@
|
||||
(function (global, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define([], factory);
|
||||
} else if (typeof exports !== "undefined") {
|
||||
factory();
|
||||
} else {
|
||||
var mod = {
|
||||
exports: {}
|
||||
};
|
||||
factory();
|
||||
global.FileSaver = mod.exports;
|
||||
}
|
||||
})(this, function () {
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
* FileSaver.js
|
||||
* A saveAs() FileSaver implementation.
|
||||
*
|
||||
* By Eli Grey, http://eligrey.com
|
||||
*
|
||||
* License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
|
||||
* source : http://purl.eligrey.com/github/FileSaver.js
|
||||
*/
|
||||
// The one and only way of getting global scope in all environments
|
||||
// https://stackoverflow.com/q/3277182/1008999
|
||||
var _global = typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : typeof global === 'object' && global.global === global ? global : void 0;
|
||||
|
||||
function bom(blob, opts) {
|
||||
if (typeof opts === 'undefined') opts = {
|
||||
autoBom: false
|
||||
};else if (typeof opts !== 'object') {
|
||||
console.warn('Deprecated: Expected third argument to be a object');
|
||||
opts = {
|
||||
autoBom: !opts
|
||||
};
|
||||
} // prepend BOM for UTF-8 XML and text/* types (including HTML)
|
||||
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
|
||||
|
||||
if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
|
||||
return new Blob([String.fromCharCode(0xFEFF), blob], {
|
||||
type: blob.type
|
||||
});
|
||||
}
|
||||
|
||||
return blob;
|
||||
}
|
||||
|
||||
function download(url, name, opts) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
xhr.responseType = 'blob';
|
||||
|
||||
xhr.onload = function () {
|
||||
saveAs(xhr.response, name, opts);
|
||||
};
|
||||
|
||||
xhr.onerror = function () {
|
||||
console.error('could not download file');
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function corsEnabled(url) {
|
||||
var xhr = new XMLHttpRequest(); // use sync to avoid popup blocker
|
||||
|
||||
xhr.open('HEAD', url, false);
|
||||
|
||||
try {
|
||||
xhr.send();
|
||||
} catch (e) {}
|
||||
|
||||
return xhr.status >= 200 && xhr.status <= 299;
|
||||
} // `a.click()` doesn't work for all browsers (#465)
|
||||
|
||||
|
||||
function click(node) {
|
||||
try {
|
||||
node.dispatchEvent(new MouseEvent('click'));
|
||||
} catch (e) {
|
||||
var evt = document.createEvent('MouseEvents');
|
||||
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
|
||||
node.dispatchEvent(evt);
|
||||
}
|
||||
} // Detect WebView inside a native macOS app by ruling out all browsers
|
||||
// We just need to check for 'Safari' because all other browsers (besides Firefox) include that too
|
||||
// https://www.whatismybrowser.com/guides/the-latest-user-agent/macos
|
||||
|
||||
|
||||
var isMacOSWebView = /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent);
|
||||
var saveAs = _global.saveAs || ( // probably in some web worker
|
||||
typeof window !== 'object' || window !== _global ? function saveAs() {}
|
||||
/* noop */
|
||||
// Use download attribute first if possible (#193 Lumia mobile) unless this is a macOS WebView
|
||||
: 'download' in HTMLAnchorElement.prototype && !isMacOSWebView ? function saveAs(blob, name, opts) {
|
||||
var URL = _global.URL || _global.webkitURL;
|
||||
var a = document.createElement('a');
|
||||
name = name || blob.name || 'download';
|
||||
a.download = name;
|
||||
a.rel = 'noopener'; // tabnabbing
|
||||
// TODO: detect chrome extensions & packaged apps
|
||||
// a.target = '_blank'
|
||||
|
||||
if (typeof blob === 'string') {
|
||||
// Support regular links
|
||||
a.href = blob;
|
||||
|
||||
if (a.origin !== location.origin) {
|
||||
corsEnabled(a.href) ? download(blob, name, opts) : click(a, a.target = '_blank');
|
||||
} else {
|
||||
click(a);
|
||||
}
|
||||
} else {
|
||||
// Support blobs
|
||||
a.href = URL.createObjectURL(blob);
|
||||
setTimeout(function () {
|
||||
URL.revokeObjectURL(a.href);
|
||||
}, 4E4); // 40s
|
||||
|
||||
setTimeout(function () {
|
||||
click(a);
|
||||
}, 0);
|
||||
}
|
||||
} // Use msSaveOrOpenBlob as a second approach
|
||||
: 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, opts) {
|
||||
name = name || blob.name || 'download';
|
||||
|
||||
if (typeof blob === 'string') {
|
||||
if (corsEnabled(blob)) {
|
||||
download(blob, name, opts);
|
||||
} else {
|
||||
var a = document.createElement('a');
|
||||
a.href = blob;
|
||||
a.target = '_blank';
|
||||
setTimeout(function () {
|
||||
click(a);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
navigator.msSaveOrOpenBlob(bom(blob, opts), name);
|
||||
}
|
||||
} // Fallback to using FileReader and a popup
|
||||
: function saveAs(blob, name, opts, popup) {
|
||||
// Open a popup immediately do go around popup blocker
|
||||
// Mostly only available on user interaction and the fileReader is async so...
|
||||
popup = popup || open('', '_blank');
|
||||
|
||||
if (popup) {
|
||||
popup.document.title = popup.document.body.innerText = 'downloading...';
|
||||
}
|
||||
|
||||
if (typeof blob === 'string') return download(blob, name, opts);
|
||||
var force = blob.type === 'application/octet-stream';
|
||||
|
||||
var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari;
|
||||
|
||||
var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
|
||||
|
||||
if ((isChromeIOS || force && isSafari || isMacOSWebView) && typeof FileReader !== 'undefined') {
|
||||
// Safari doesn't allow downloading of blob URLs
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onloadend = function () {
|
||||
var url = reader.result;
|
||||
url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;');
|
||||
if (popup) popup.location.href = url;else location = url;
|
||||
popup = null; // reverse-tabnabbing #460
|
||||
};
|
||||
|
||||
reader.readAsDataURL(blob);
|
||||
} else {
|
||||
var URL = _global.URL || _global.webkitURL;
|
||||
var url = URL.createObjectURL(blob);
|
||||
if (popup) popup.location = url;else location.href = url;
|
||||
popup = null; // reverse-tabnabbing #460
|
||||
|
||||
setTimeout(function () {
|
||||
URL.revokeObjectURL(url);
|
||||
}, 4E4); // 40s
|
||||
}
|
||||
});
|
||||
_global.saveAs = saveAs.saveAs = saveAs;
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = saveAs;
|
||||
}
|
||||
});
|
||||
1041
static/html/jspaint/lib/UPNG.js
Normal file
1041
static/html/jspaint/lib/UPNG.js
Normal file
File diff suppressed because it is too large
Load Diff
1252
static/html/jspaint/lib/UTIF.js
Normal file
1252
static/html/jspaint/lib/UTIF.js
Normal file
File diff suppressed because it is too large
Load Diff
11803
static/html/jspaint/lib/anypalette-0.6.0.js
Normal file
11803
static/html/jspaint/lib/anypalette-0.6.0.js
Normal file
File diff suppressed because it is too large
Load Diff
655
static/html/jspaint/lib/bmp.js
Normal file
655
static/html/jspaint/lib/bmp.js
Normal file
@@ -0,0 +1,655 @@
|
||||
/**
|
||||
* Based on: https://github.com/shaozilee/bmp-js/blob/db2c466ca1869ddc09e4b2143404eb03ecd490db/lib/encoder.js
|
||||
* @author shaozilee
|
||||
* @author 1j01
|
||||
* @license MIT
|
||||
*
|
||||
* BMP format encoder, encodes 24bit, 8bit, 4bit, and 1bit BMP files.
|
||||
* Doesn't support compression.
|
||||
*
|
||||
*/
|
||||
|
||||
function encodeBMP(imgData, bitsPerPixel = 24) {
|
||||
if (![1, 4, 8, 24/*, 32*/].includes(bitsPerPixel)) {
|
||||
throw new Error(`not supported: ${bitsPerPixel} bits per pixel`)
|
||||
}
|
||||
const bytesPerPixel = bitsPerPixel / 8; // can be more or less than one
|
||||
// Rows are always a multiple of 4 bytes long.
|
||||
const pixelRowSize = Math.ceil(imgData.width * bytesPerPixel / 4) * 4;
|
||||
const pixelDataSize = imgData.height * pixelRowSize;
|
||||
const headerInfoSize = 40;
|
||||
const indexed = bitsPerPixel <= 8;
|
||||
const maxColorCount = 2 ** bitsPerPixel;
|
||||
|
||||
let rgbTable;
|
||||
let indices;
|
||||
let colorCount = 0;
|
||||
if (indexed) {
|
||||
// rgbTable = [];
|
||||
// for (const color of palette.slice(0, maxColorCount)) {
|
||||
// const [r, g, b] = get_rgba_from_color(color);
|
||||
// rgbTable.push([r, g, b]);
|
||||
// }
|
||||
const res = UPNG.quantize(imgData.data, maxColorCount);
|
||||
indices = res.inds;
|
||||
rgbTable = res.plte.map((color_entry) => color_entry.est.q.map((component) => Math.round(component * 255)));
|
||||
colorCount = rgbTable.length;
|
||||
}
|
||||
|
||||
const flag = "BM";
|
||||
const planes = 1;
|
||||
const compressionType = 0;// bitsPerPixel === 32 ? 3 : 0
|
||||
const hr = 0;
|
||||
const vr = 0;
|
||||
const importantColorCount = 0; // 0 means all colors are important
|
||||
|
||||
const colorTableSize = colorCount * 4;
|
||||
const offsetToPixelData = 54 + colorTableSize;
|
||||
const fileSize = pixelDataSize + offsetToPixelData;
|
||||
|
||||
const fileArrayBuffer = new ArrayBuffer(fileSize);
|
||||
const view = new DataView(fileArrayBuffer);
|
||||
let pos = 0;
|
||||
// BMP header
|
||||
view.setUint8(pos, flag.charCodeAt(0)); pos += 1;
|
||||
view.setUint8(pos, flag.charCodeAt(1)); pos += 1;
|
||||
view.setUint32(pos, fileSize, true); pos += 4;
|
||||
pos += 4; // reserved / application-specific
|
||||
view.setUint32(pos, offsetToPixelData, true); pos += 4;
|
||||
// DIB header
|
||||
view.setUint32(pos, headerInfoSize, true); pos += 4;
|
||||
view.setInt32(pos, imgData.width, true); pos += 4;
|
||||
view.setInt32(pos, -imgData.height, true); pos += 4; // negative indicates rows are stored top to bottom
|
||||
view.setUint16(pos, planes, true); pos += 2;
|
||||
view.setUint16(pos, bitsPerPixel, true); pos += 2;
|
||||
view.setUint32(pos, compressionType, true); pos += 4;
|
||||
view.setUint32(pos, pixelDataSize, true); pos += 4;
|
||||
view.setInt32(pos, hr, true); pos += 4;
|
||||
view.setInt32(pos, vr, true); pos += 4;
|
||||
view.setUint32(pos, colorCount, true); pos += 4;
|
||||
view.setUint32(pos, importantColorCount, true); pos += 4;
|
||||
|
||||
if (rgbTable) {
|
||||
for (const [r, g, b] of rgbTable) {
|
||||
view.setUint8(pos, b); pos += 1;
|
||||
view.setUint8(pos, g); pos += 1;
|
||||
view.setUint8(pos, r); pos += 1;
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
|
||||
const getColorIndex = (imgDataIndex) => {
|
||||
return indices[imgDataIndex / 4];
|
||||
};
|
||||
|
||||
let i = 0;
|
||||
for (let y = 0; y < imgData.height; y += 1) {
|
||||
for (let x = 0; x < imgData.width;) {
|
||||
const pixelGroupPos = pos + y * pixelRowSize + x * bytesPerPixel;
|
||||
if (bitsPerPixel === 1) {
|
||||
let byte = 0;
|
||||
for (let j = 0; j < 8 && x + j < imgData.width; j += 1) {
|
||||
byte |= getColorIndex(i) << (7 - j);
|
||||
i += 4;
|
||||
}
|
||||
view.setUint8(pixelGroupPos, byte);
|
||||
x += 8;
|
||||
} else if (bitsPerPixel === 4) {
|
||||
let byte = 0;
|
||||
for (let j = 0; j < 2 && x + j < imgData.width; j += 1) {
|
||||
byte |= getColorIndex(i) << (4 * (1 - j));
|
||||
i += 4;
|
||||
}
|
||||
view.setUint8(pixelGroupPos, byte);
|
||||
x += 2;
|
||||
} else if (bitsPerPixel === 8) {
|
||||
view.setUint8(pixelGroupPos, getColorIndex(i));
|
||||
i += 4;
|
||||
x += 1;
|
||||
} else {
|
||||
view.setUint8(pixelGroupPos + 2, imgData.data[i + 0]); // red
|
||||
view.setUint8(pixelGroupPos + 1, imgData.data[i + 1]); // green
|
||||
view.setUint8(pixelGroupPos + 0, imgData.data[i + 2]); // blue
|
||||
// if (bitsPerPixel === 32) {
|
||||
// view.setUint8(pixelGroupPos + 3, imgData.data[i + 3]); // alpha
|
||||
// }
|
||||
i += 4;
|
||||
x += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return view.buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on https://github.com/ericandrewlewis/bitmap-js/blob/c33a6137829b18e3420a763ef20bffae874610b3/index.js
|
||||
* @author ericandrewlewis
|
||||
* @license MIT
|
||||
*/
|
||||
/*
|
||||
function decodeBMP(arrayBuffer) {
|
||||
function readBitmapFileHeader(view) {
|
||||
if (view.getUint8(0) !== "B".charCodeAt(0) || view.getUint8(1) !== "M".charCodeAt(0)) {
|
||||
throw new Error("not a BMP file"); // Note: exact error message is checked for to detect this case
|
||||
}
|
||||
return {
|
||||
filesize: view.getUint32(2, true),
|
||||
imageDataOffset: view.getUint32(10, true)
|
||||
};
|
||||
}
|
||||
|
||||
const dibHeaderLengthToVersionMap = {
|
||||
12: "BITMAPCOREHEADER",
|
||||
16: "OS22XBITMAPHEADER",
|
||||
40: "BITMAPINFOHEADER",
|
||||
52: "BITMAPV2INFOHEADER",
|
||||
56: "BITMAPV3INFOHEADER",
|
||||
64: "OS22XBITMAPHEADER",
|
||||
108: "BITMAPV4HEADER",
|
||||
124: "BITMAPV5HEADER"
|
||||
};
|
||||
|
||||
function readDibHeader(view) {
|
||||
const dibHeaderLength = view.getUint32(14, true);
|
||||
const header = {};
|
||||
header.headerLength = dibHeaderLength;
|
||||
header.headerType = dibHeaderLengthToVersionMap[dibHeaderLength];
|
||||
header.width = view.getInt32(18, true);
|
||||
header.height = view.getInt32(22, true); // Note: negative is used to mean rows go top to bottom instead of bottom to top
|
||||
if (header.headerType == "BITMAPCOREHEADER") {
|
||||
return header;
|
||||
}
|
||||
header.bitsPerPixel = view.getUint16(28, true);
|
||||
header.compressionType = view.getUint32(30, true);
|
||||
if (header.headerType == "OS22XBITMAPHEADER") {
|
||||
return header;
|
||||
}
|
||||
header.bitmapDataSize = view.getUint32(34, true);
|
||||
header.numberOfColorsInPalette = view.getUint32(46, true);
|
||||
header.numberOfImportantColors = view.getUint32(50, true);
|
||||
if (header.headerType == "BITMAPINFOHEADER") {
|
||||
return header;
|
||||
}
|
||||
// There are more data fields in later versions of the dib header.
|
||||
// I hear that BITMAPINFOHEADER is the most widely supported
|
||||
// header type, so I'm not going to implement them yet.
|
||||
return header;
|
||||
}
|
||||
|
||||
function readColorTable(view) {
|
||||
const dibHeader = readDibHeader(view);
|
||||
const colorTable = [];
|
||||
const sourceStart = 14 + dibHeader.headerLength;
|
||||
const numberOfColorsInPalette = dibHeader.numberOfColorsInPalette || (dibHeader.bitsPerPixel <= 8 ? 2 ** dibHeader.bitsPerPixel : 0);
|
||||
for (let i = 0; i < numberOfColorsInPalette; i += 1) {
|
||||
colorTable.push({
|
||||
r: view.getUint8(sourceStart + i * 4 + 2),
|
||||
g: view.getUint8(sourceStart + i * 4 + 1),
|
||||
b: view.getUint8(sourceStart + i * 4 + 0),
|
||||
});
|
||||
}
|
||||
return colorTable;
|
||||
}
|
||||
|
||||
const view = new DataView(arrayBuffer);
|
||||
const fileHeader = readBitmapFileHeader(view);
|
||||
const dibHeader = readDibHeader(view);
|
||||
// const imageDataLength = dibHeader.bitmapDataSize;
|
||||
// const imageDataOffset = fileHeader.imageDataOffset;
|
||||
const colorTable = readColorTable(view);
|
||||
// view.copy(imageData, 0, imageDataOffset);
|
||||
const width = Math.abs(fileHeader.width);
|
||||
const height = Math.abs(fileHeader.height); // negative is used to mean rows go top to bottom instead of bottom to top
|
||||
// const imageData = new ImageData(width, height);
|
||||
// const pixelRowSize = Math.ceil(width * dibHeader.bitsPerPixel / 8 / 4) * 4;
|
||||
// for (let y = 0; y < height; y += 1) {
|
||||
// for (let x = 0; x < width; x += 1) {
|
||||
// const byte = view.readUint8(y * pixelRowSize + x * dibHeader.bitsPerPixel / 8);
|
||||
// imageData.data[y * height * 4 + 0,1,2,3] = ...;
|
||||
// }
|
||||
// }
|
||||
return {
|
||||
// width,
|
||||
// height,
|
||||
// fileHeader,
|
||||
// dibHeader,
|
||||
// imageData,
|
||||
colorTable,
|
||||
bitsPerPixel: dibHeader.bitsPerPixel,
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
function decodeBMP(arrayBuffer) {
|
||||
const decoder = new BmpDecoder(arrayBuffer, {toRGBA: true});
|
||||
return {
|
||||
bitsPerPixel: decoder.bitsPerPixel,
|
||||
colorTable: decoder.palette ? decoder.palette.map(({red, green, blue})=> ({r: red, g: green, b: blue})) : [],
|
||||
imageData: new ImageData(decoder.data, decoder.width, decoder.height),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on: https://github.com/hipstersmoothie/bmp-ts
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
const HeaderTypes = {};
|
||||
HeaderTypes[HeaderTypes["BITMAP_INFO_HEADER"] = 40] = "BITMAP_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V2_INFO_HEADER"] = 52] = "BITMAP_V2_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V3_INFO_HEADER"] = 56] = "BITMAP_V3_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V4_HEADER"] = 108] = "BITMAP_V4_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V5_HEADER"] = 124] = "BITMAP_V5_HEADER";
|
||||
Object.freeze(HeaderTypes);
|
||||
|
||||
// We have these:
|
||||
//
|
||||
// const sample = 0101 0101 0101 0101
|
||||
// const mask = 0111 1100 0000 0000
|
||||
// 256 === 0000 0001 0000 0000
|
||||
//
|
||||
// We want to take the sample and turn it into an 8-bit value.
|
||||
//
|
||||
// 1. We extract the last bit of the mask:
|
||||
//
|
||||
// 0000 0100 0000 0000
|
||||
// ^
|
||||
//
|
||||
// Like so:
|
||||
//
|
||||
// const a = ~mask = 1000 0011 1111 1111
|
||||
// const b = a + 1 = 1000 0100 0000 0000
|
||||
// const c = b & mask = 0000 0100 0000 0000
|
||||
//
|
||||
// 2. We shift it to the right and extract the bit before the first:
|
||||
//
|
||||
// 0000 0000 0010 0000
|
||||
// ^
|
||||
//
|
||||
// Like so:
|
||||
//
|
||||
// const d = mask / c = 0000 0000 0001 1111
|
||||
// const e = mask + 1 = 0000 0000 0010 0000
|
||||
//
|
||||
// 3. We apply the mask and the two values above to a sample:
|
||||
//
|
||||
// const f = sample & mask = 0101 0100 0000 0000
|
||||
// const g = f / c = 0000 0000 0001 0101
|
||||
// const h = 256 / e = 0000 0000 0000 0100
|
||||
// const i = g * h = 0000 0000 1010 1000
|
||||
// ^^^^ ^
|
||||
//
|
||||
// Voila, we have extracted a sample and "stretched" it to 8 bits. For samples
|
||||
// which are already 8-bit, h === 1 and g === i.
|
||||
function maskColor(maskRed, maskGreen, maskBlue, maskAlpha) {
|
||||
const maskRedR = (~maskRed + 1) & maskRed;
|
||||
const maskGreenR = (~maskGreen + 1) & maskGreen;
|
||||
const maskBlueR = (~maskBlue + 1) & maskBlue;
|
||||
const maskAlphaR = (~maskAlpha + 1) & maskAlpha;
|
||||
const shiftedMaskRedL = maskRed / maskRedR + 1;
|
||||
const shiftedMaskGreenL = maskGreen / maskGreenR + 1;
|
||||
const shiftedMaskBlueL = maskBlue / maskBlueR + 1;
|
||||
const shiftedMaskAlphaL = maskAlpha / maskAlphaR + 1;
|
||||
return {
|
||||
shiftRed: (x) => (((x & maskRed) / maskRedR) * 0x100) / shiftedMaskRedL,
|
||||
shiftGreen: (x) => (((x & maskGreen) / maskGreenR) * 0x100) / shiftedMaskGreenL,
|
||||
shiftBlue: (x) => (((x & maskBlue) / maskBlueR) * 0x100) / shiftedMaskBlueL,
|
||||
shiftAlpha: maskAlpha !== 0
|
||||
? (x) => (((x & maskAlpha) / maskAlphaR) * 0x100) / shiftedMaskAlphaL
|
||||
: () => 255
|
||||
};
|
||||
}
|
||||
class BmpDecoder {
|
||||
constructor(arrayBuffer, { toRGBA } = { toRGBA: false }) {
|
||||
this.view = new DataView(arrayBuffer);
|
||||
this.toRGBA = !!toRGBA;
|
||||
this.pos = 0;
|
||||
this.bottomUp = true;
|
||||
this.flag = String.fromCharCode(this.view.getUint8(0)) + String.fromCharCode(this.view.getUint8(1));
|
||||
this.pos += 2;
|
||||
if (this.flag !== 'BM') {
|
||||
throw new Error('Invalid BMP File');
|
||||
}
|
||||
this.locRed = this.toRGBA ? 0 : 3;
|
||||
this.locGreen = this.toRGBA ? 1 : 2;
|
||||
this.locBlue = this.toRGBA ? 2 : 1;
|
||||
this.locAlpha = this.toRGBA ? 3 : 0;
|
||||
this.parseHeader();
|
||||
this.parseRGBA();
|
||||
}
|
||||
parseHeader() {
|
||||
this.fileSize = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
this.reserved1 = this.view.getUint16(this.pos, true); this.pos += 2;
|
||||
this.reserved2 = this.view.getUint16(this.pos, true); this.pos += 2;
|
||||
this.offset = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
// End of BITMAP_FILE_HEADER
|
||||
this.headerSize = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
if (!(this.headerSize in HeaderTypes)) {
|
||||
throw new Error(`Unsupported BMP header size ${this.headerSize}`);
|
||||
}
|
||||
this.width = this.view.getInt32(this.pos, true); this.pos += 4;
|
||||
this.height = this.view.getInt32(this.pos, true); this.pos += 4;
|
||||
if (this.height < 0) {
|
||||
this.height *= -1;
|
||||
this.bottomUp = false;
|
||||
}
|
||||
this.planes = this.view.getUint16(this.pos, true); this.pos += 2;
|
||||
this.bitsPerPixel = this.view.getUint16(this.pos, true); this.pos += 2;
|
||||
this.compression = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
this.rawSize = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
this.hr = this.view.getInt32(this.pos, true); this.pos += 4;
|
||||
this.vr = this.view.getInt32(this.pos, true); this.pos += 4;
|
||||
this.colors = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
this.importantColors = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
// De facto defaults
|
||||
if (this.bitsPerPixel === 32) {
|
||||
this.maskAlpha = 0;
|
||||
this.maskRed = 0x00ff0000;
|
||||
this.maskGreen = 0x0000ff00;
|
||||
this.maskBlue = 0x000000ff;
|
||||
}
|
||||
else if (this.bitsPerPixel === 16) {
|
||||
this.maskAlpha = 0;
|
||||
this.maskRed = 0x7c00;
|
||||
this.maskGreen = 0x03e0;
|
||||
this.maskBlue = 0x001f;
|
||||
}
|
||||
// End of BITMAP_INFO_HEADER
|
||||
if (this.headerSize > HeaderTypes.BITMAP_INFO_HEADER ||
|
||||
this.compression === 3 /* BI_BIT_FIELDS */ ||
|
||||
this.compression === 6 /* BI_ALPHA_BIT_FIELDS */) {
|
||||
this.maskRed = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
this.maskGreen = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
this.maskBlue = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
}
|
||||
// End of BITMAP_V2_INFO_HEADER
|
||||
if (this.headerSize > HeaderTypes.BITMAP_V2_INFO_HEADER ||
|
||||
this.compression === 6 /* BI_ALPHA_BIT_FIELDS */) {
|
||||
this.maskAlpha = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
}
|
||||
// End of BITMAP_V3_INFO_HEADER
|
||||
if (this.headerSize > HeaderTypes.BITMAP_V3_INFO_HEADER) {
|
||||
this.pos +=
|
||||
HeaderTypes.BITMAP_V4_HEADER - HeaderTypes.BITMAP_V3_INFO_HEADER;
|
||||
}
|
||||
// End of BITMAP_V4_HEADER
|
||||
if (this.headerSize > HeaderTypes.BITMAP_V4_HEADER) {
|
||||
this.pos += HeaderTypes.BITMAP_V5_HEADER - HeaderTypes.BITMAP_V4_HEADER;
|
||||
}
|
||||
// End of BITMAP_V5_HEADER
|
||||
if (this.bitsPerPixel <= 8 || this.colors > 0) {
|
||||
const len = this.colors === 0 ? 1 << this.bitsPerPixel : this.colors;
|
||||
this.palette = new Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
const blue = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const green = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const red = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const quad = this.view.getUint8(this.pos); this.pos += 1;
|
||||
this.palette[i] = {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
quad
|
||||
};
|
||||
}
|
||||
}
|
||||
// End of color table
|
||||
const coloShift = maskColor(this.maskRed, this.maskGreen, this.maskBlue, this.maskAlpha);
|
||||
this.shiftRed = coloShift.shiftRed;
|
||||
this.shiftGreen = coloShift.shiftGreen;
|
||||
this.shiftBlue = coloShift.shiftBlue;
|
||||
this.shiftAlpha = coloShift.shiftAlpha;
|
||||
}
|
||||
parseRGBA() {
|
||||
this.data = new Uint8ClampedArray(this.width * this.height * 4);
|
||||
switch (this.bitsPerPixel) {
|
||||
case 1:
|
||||
this.parse1bpp();
|
||||
break;
|
||||
case 4:
|
||||
this.parse4bpp();
|
||||
break;
|
||||
case 8:
|
||||
this.parse8bpp();
|
||||
break;
|
||||
case 16:
|
||||
this.parse16bpp();
|
||||
break;
|
||||
case 24:
|
||||
this.parse24bpp();
|
||||
break;
|
||||
default:
|
||||
this.parse32bpp();
|
||||
}
|
||||
}
|
||||
parse1bpp() {
|
||||
const xLen = Math.ceil(this.width / 8);
|
||||
const mode = xLen % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
let lastLine;
|
||||
this.scanImage(padding, xLen, (x, line) => {
|
||||
if (line !== lastLine) {
|
||||
lastLine = line;
|
||||
}
|
||||
const b = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const location = line * this.width * 4 + x * 8 * 4;
|
||||
for (let i = 0; i < 8; i++) {
|
||||
if (x * 8 + i < this.width) {
|
||||
// @TODO: use setPixelData?
|
||||
const rgb = this.palette[(b >> (7 - i)) & 0x1];
|
||||
this.data[location + i * 4 + this.locAlpha] = 255;
|
||||
this.data[location + i * 4 + this.locBlue] = rgb.blue;
|
||||
this.data[location + i * 4 + this.locGreen] = rgb.green;
|
||||
this.data[location + i * 4 + this.locRed] = rgb.red;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
parse4bpp() {
|
||||
if (this.compression === 2 /* BI_RLE4 */) {
|
||||
let lowNibble = false; //for all count of pixel
|
||||
let lines = this.bottomUp ? this.height - 1 : 0;
|
||||
let location = 0;
|
||||
while (location < this.data.length) {
|
||||
const a = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const b = this.view.getUint8(this.pos); this.pos += 1;
|
||||
//absolute mode
|
||||
if (a === 0) {
|
||||
if (b === 0) {
|
||||
//line end
|
||||
lines += this.bottomUp ? -1 : 1;
|
||||
location = lines * this.width * 4;
|
||||
lowNibble = false;
|
||||
continue;
|
||||
}
|
||||
if (b === 1) {
|
||||
// image end
|
||||
break;
|
||||
}
|
||||
if (b === 2) {
|
||||
// offset x, y
|
||||
const x = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const y = this.view.getUint8(this.pos); this.pos += 1;
|
||||
lines += this.bottomUp ? -y : y;
|
||||
location += y * this.width * 4 + x * 4;
|
||||
}
|
||||
else {
|
||||
let c = this.view.getUint8(this.pos); this.pos += 1;
|
||||
for (let i = 0; i < b; i++) {
|
||||
location = this.setPixelData(location, lowNibble ? c & 0x0f : (c & 0xf0) >> 4);
|
||||
if (i & 1 && i + 1 < b) {
|
||||
c = this.view.getUint8(this.pos); this.pos += 1;
|
||||
}
|
||||
lowNibble = !lowNibble;
|
||||
}
|
||||
if ((((b + 1) >> 1) & 1) === 1) {
|
||||
this.pos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//encoded mode
|
||||
for (let i = 0; i < a; i++) {
|
||||
location = this.setPixelData(location, lowNibble ? b & 0x0f : (b & 0xf0) >> 4);
|
||||
lowNibble = !lowNibble;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const xLen = Math.ceil(this.width / 2);
|
||||
const mode = xLen % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
this.scanImage(padding, xLen, (x, line) => {
|
||||
const b = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const location = line * this.width * 4 + x * 2 * 4;
|
||||
const first4 = b >> 4;
|
||||
// @TODO: use setPixelData?
|
||||
let rgb = this.palette[first4];
|
||||
this.data[location + this.locAlpha] = 255;
|
||||
this.data[location + this.locBlue] = rgb.blue;
|
||||
this.data[location + this.locGreen] = rgb.green;
|
||||
this.data[location + this.locRed] = rgb.red;
|
||||
if (x * 2 + 1 >= this.width) {
|
||||
// throw new Error('Something');
|
||||
return false;
|
||||
}
|
||||
const last4 = b & 0x0f;
|
||||
// @TODO: use setPixelData?
|
||||
rgb = this.palette[last4];
|
||||
this.data[location + 4 + this.locAlpha] = 255;
|
||||
this.data[location + 4 + this.locBlue] = rgb.blue;
|
||||
this.data[location + 4 + this.locGreen] = rgb.green;
|
||||
this.data[location + 4 + this.locRed] = rgb.red;
|
||||
});
|
||||
}
|
||||
}
|
||||
parse8bpp() {
|
||||
if (this.compression === 1 /* BI_RLE8 */) {
|
||||
let lines = this.bottomUp ? this.height - 1 : 0;
|
||||
let location = 0;
|
||||
while (location < this.data.length) {
|
||||
const a = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const b = this.view.getUint8(this.pos); this.pos += 1;
|
||||
//absolute mode
|
||||
if (a === 0) {
|
||||
if (b === 0) {
|
||||
//line end
|
||||
lines += this.bottomUp ? -1 : 1;
|
||||
location = lines * this.width * 4;
|
||||
continue;
|
||||
}
|
||||
if (b === 1) {
|
||||
//image end
|
||||
break;
|
||||
}
|
||||
if (b === 2) {
|
||||
//offset x,y
|
||||
const x = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const y = this.view.getUint8(this.pos); this.pos += 1;
|
||||
lines += this.bottomUp ? -y : y;
|
||||
location += y * this.width * 4 + x * 4;
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < b; i++) {
|
||||
const c = this.view.getUint8(this.pos); this.pos += 1;
|
||||
location = this.setPixelData(location, c);
|
||||
}
|
||||
// why 1 === 1???
|
||||
// eslint-disable-next-line no-self-compare
|
||||
const shouldIncrement = b & (1 === 1);
|
||||
if (shouldIncrement) {
|
||||
this.pos += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//encoded mode
|
||||
for (let i = 0; i < a; i++) {
|
||||
location = this.setPixelData(location, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const mode = this.width % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const b = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const location = line * this.width * 4 + x * 4;
|
||||
// @TODO: use setPixelData?
|
||||
if (b < this.palette.length) {
|
||||
const rgb = this.palette[b];
|
||||
this.data[location + this.locRed] = rgb.red;
|
||||
this.data[location + this.locGreen] = rgb.green;
|
||||
this.data[location + this.locBlue] = rgb.blue;
|
||||
this.data[location + this.locAlpha] = 0xff;
|
||||
}
|
||||
else {
|
||||
this.data[location] = 0xff;
|
||||
this.data[location + 1] = 0xff;
|
||||
this.data[location + 2] = 0xff;
|
||||
this.data[location + 3] = 0xff;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
parse16bpp() {
|
||||
const padding = (this.width % 2) * 2;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const px = this.view.getUint16(this.pos, true); this.pos += 2;
|
||||
this.data[loc + this.locRed] = this.shiftRed(px);
|
||||
this.data[loc + this.locGreen] = this.shiftGreen(px);
|
||||
this.data[loc + this.locBlue] = this.shiftBlue(px);
|
||||
this.data[loc + this.locAlpha] = 255; //this.shiftAlpha(px); // @TODO??
|
||||
});
|
||||
}
|
||||
parse24bpp() {
|
||||
const padding = this.width % 4;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const blue = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const green = this.view.getUint8(this.pos); this.pos += 1;
|
||||
const red = this.view.getUint8(this.pos); this.pos += 1;
|
||||
this.data[loc + this.locRed] = red;
|
||||
this.data[loc + this.locGreen] = green;
|
||||
this.data[loc + this.locBlue] = blue;
|
||||
this.data[loc + this.locAlpha] = 255;
|
||||
});
|
||||
}
|
||||
parse32bpp() {
|
||||
this.scanImage(0, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const px = this.view.getUint32(this.pos, true); this.pos += 4;
|
||||
this.data[loc + this.locRed] = this.shiftRed(px);
|
||||
this.data[loc + this.locGreen] = this.shiftGreen(px);
|
||||
this.data[loc + this.locBlue] = this.shiftBlue(px);
|
||||
this.data[loc + this.locAlpha] = this.shiftAlpha(px);
|
||||
});
|
||||
}
|
||||
scanImage(padding = 0, width = this.width, processPixel) {
|
||||
for (let y = this.height - 1; y >= 0; y--) {
|
||||
const line = this.bottomUp ? y : this.height - 1 - y;
|
||||
for (let x = 0; x < width; x++) {
|
||||
const result = processPixel.call(this, x, line);
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.pos += padding;
|
||||
}
|
||||
}
|
||||
setPixelData(location, rgbIndex) {
|
||||
const { blue, green, red } = this.palette[rgbIndex];
|
||||
this.data[location + this.locAlpha] = 255;
|
||||
this.data[location + this.locBlue] = blue;
|
||||
this.data[location + this.locGreen] = green;
|
||||
this.data[location + this.locRed] = red;
|
||||
return location + 4;
|
||||
}
|
||||
}
|
||||
36
static/html/jspaint/lib/firebase.js
Normal file
36
static/html/jspaint/lib/firebase.js
Normal file
File diff suppressed because one or more lines are too long
196
static/html/jspaint/lib/font-detective.js
Normal file
196
static/html/jspaint/lib/font-detective.js
Normal file
@@ -0,0 +1,196 @@
|
||||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
var after, domReady, every;
|
||||
|
||||
after = function(ms, fn) {
|
||||
var tid;
|
||||
tid = setTimeout(fn, ms);
|
||||
return {
|
||||
stop: function() {
|
||||
return clearTimeout(tid);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
every = function(ms, fn) {
|
||||
var iid;
|
||||
iid = setInterval(fn, ms);
|
||||
return {
|
||||
stop: function() {
|
||||
return clearInterval(iid);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
domReady = function(callback) {
|
||||
if (/in/.test(document.readyState)) {
|
||||
return after(10, function() {
|
||||
return domReady(callback);
|
||||
});
|
||||
} else {
|
||||
return callback();
|
||||
}
|
||||
};
|
||||
|
||||
(function(exports) {
|
||||
var FD, Font, container, doneTestingFonts, fontAvailabilityChecker, genericFontFamilies, loadFonts, someCommonFontNames, startedLoading, testFonts, testedFonts;
|
||||
FD = exports.FontDetective = {};
|
||||
genericFontFamilies = ["serif", "sans-serif", "cursive", "fantasy", "monospace"];
|
||||
someCommonFontNames = "Helvetica,Lucida Grande,Lucida Sans,Tahoma,Arial,Geneva,Monaco,Verdana,Microsoft Sans Serif,Trebuchet MS,Courier New,Times New Roman,Courier,Lucida Bright,Lucida Sans Typewriter,URW Chancery L,Comic Sans MS,Georgia,Palatino Linotype,Lucida Sans Unicode,Times,Century Schoolbook L,URW Gothic L,Franklin Gothic Medium,Lucida Console,Impact,URW Bookman L,Helvetica Neue,Nimbus Sans L,URW Palladio L,Nimbus Mono L,Nimbus Roman No9 L,Arial Black,Sylfaen,MV Boli,Estrangelo Edessa,Tunga,Gautami,Raavi,Mangal,Shruti,Latha,Kartika,Vrinda,Arial Narrow,Century Gothic,Garamond,Book Antiqua,Bookman Old Style,Calibri,Cambria,Candara,Corbel,Monotype Corsiva,Cambria Math,Consolas,Constantia,MS Reference Sans Serif,MS Mincho,Segoe UI,Arial Unicode MS,Tempus Sans ITC,Kristen ITC,Mistral,Meiryo UI,Juice ITC,Papyrus,Bradley Hand ITC,French Script MT,Malgun Gothic,Microsoft YaHei,Gisha,Leelawadee,Microsoft JhengHei,Haettenschweiler,Microsoft Himalaya,Microsoft Uighur,MoolBoran,Jokerman,DFKai-SB,KaiTi,SimSun-ExtB,Freestyle Script,Vivaldi,FangSong,MingLiU-ExtB,MingLiU_HKSCS,MingLiU_HKSCS-ExtB,PMingLiU-ExtB,Copperplate Gothic Light,Copperplate Gothic Bold,Franklin Gothic Book,Maiandra GD,Perpetua,Eras Demi ITC,Felix Titling,Franklin Gothic Demi,Pristina,Edwardian Script ITC,OCR A Extended,Engravers MT,Eras Light ITC,Franklin Gothic Medium Cond,Rockwell Extra Bold,Rockwell,Curlz MT,Blackadder ITC,Franklin Gothic Heavy,Franklin Gothic Demi Cond,Lucida Handwriting,Segoe UI Light,Segoe UI Semibold,Lucida Calligraphy,Cooper Black,Viner Hand ITC,Britannic Bold,Wide Latin,Old English Text MT,Broadway,Footlight MT Light,Harrington,Snap ITC,Onyx,Playbill,Bauhaus 93,Baskerville Old Face,Algerian,Matura MT Script Capitals,Stencil,Batang,Chiller,Harlow Solid Italic,Kunstler Script,Bernard MT Condensed,Informal Roman,Vladimir Script,Bell MT,Colonna MT,High Tower Text,Californian FB,Ravie,Segoe Script,Brush Script MT,SimSun,Arial Rounded MT Bold,Berlin Sans FB,Centaur,Niagara Solid,Showcard Gothic,Niagara Engraved,Segoe Print,Gabriola,Gill Sans MT,Iskoola Pota,Calisto MT,Script MT Bold,Century Schoolbook,Berlin Sans FB Demi,Magneto,Arabic Typesetting,DaunPenh,Mongolian Baiti,DokChampa,Euphemia,Kalinga,Microsoft Yi Baiti,Nyala,Bodoni MT Poster Compressed,Goudy Old Style,Imprint MT Shadow,Gill Sans MT Condensed,Gill Sans Ultra Bold,Palace Script MT,Lucida Fax,Gill Sans MT Ext Condensed Bold,Goudy Stout,Eras Medium ITC,Rage Italic,Rockwell Condensed,Castellar,Eras Bold ITC,Forte,Gill Sans Ultra Bold Condensed,Perpetua Titling MT,Agency FB,Tw Cen MT,Gigi,Tw Cen MT Condensed,Aparajita,Gloucester MT Extra Condensed,Tw Cen MT Condensed Extra Bold,PMingLiU,Bodoni MT,Bodoni MT Black,Bodoni MT Condensed,MS Gothic,GulimChe,MS UI Gothic,MS PGothic,Gulim,MS PMincho,BatangChe,Dotum,DotumChe,Gungsuh,GungsuhChe,MingLiU,NSimSun,SimHei,DejaVu Sans,DejaVu Sans Condensed,DejaVu Sans Mono,DejaVu Serif,DejaVu Serif Condensed,Eurostile,Matisse ITC,Bitstream Vera Sans Mono,Bitstream Vera Sans,Staccato222 BT,Bitstream Vera Serif,Broadway BT,ParkAvenue BT,Square721 BT,Calligraph421 BT,MisterEarl BT,Cataneo BT,Ruach LET,Rage Italic LET,La Bamba LET,Blackletter686 BT,John Handy LET,Scruff LET,Westwood LET".split(",").sort();
|
||||
testedFonts = [];
|
||||
doneTestingFonts = false;
|
||||
startedLoading = false;
|
||||
container = document.createElement("div");
|
||||
container.id = "font-detective";
|
||||
|
||||
/*
|
||||
* A font class that can be stringified for use in css
|
||||
* e.g. font.toString() or (font + ", sans-serif")
|
||||
*/
|
||||
Font = (function() {
|
||||
function Font(name, type, style) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
Font.prototype.toString = function() {
|
||||
return '"' + this.name.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + '"';
|
||||
};
|
||||
|
||||
return Font;
|
||||
|
||||
})();
|
||||
fontAvailabilityChecker = (function() {
|
||||
var baseFontFamilies, baseHeights, baseWidths, span;
|
||||
baseFontFamilies = ["monospace", "sans-serif", "serif"];
|
||||
span = document.createElement("span");
|
||||
span.innerHTML = "mmmmmmmmmmlli";
|
||||
span.style.fontSize = "72px";
|
||||
baseWidths = {};
|
||||
baseHeights = {};
|
||||
return {
|
||||
init: function() {
|
||||
var baseFontFamily, j, len, results;
|
||||
document.body.appendChild(container);
|
||||
results = [];
|
||||
for (j = 0, len = baseFontFamilies.length; j < len; j++) {
|
||||
baseFontFamily = baseFontFamilies[j];
|
||||
span.style.fontFamily = baseFontFamily;
|
||||
container.appendChild(span);
|
||||
baseWidths[baseFontFamily] = span.offsetWidth;
|
||||
baseHeights[baseFontFamily] = span.offsetHeight;
|
||||
results.push(container.removeChild(span));
|
||||
}
|
||||
return results;
|
||||
},
|
||||
check: function(font) {
|
||||
var baseFontFamily, differs, j, len;
|
||||
for (j = 0, len = baseFontFamilies.length; j < len; j++) {
|
||||
baseFontFamily = baseFontFamilies[j];
|
||||
span.style.fontFamily = font + ", " + baseFontFamily;
|
||||
container.appendChild(span);
|
||||
differs = span.offsetWidth !== baseWidths[baseFontFamily] || span.offsetHeight !== baseHeights[baseFontFamily];
|
||||
container.removeChild(span);
|
||||
if (differs) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
})();
|
||||
loadFonts = function() {
|
||||
if (startedLoading) {
|
||||
return;
|
||||
}
|
||||
startedLoading = true;
|
||||
FD.incomplete = true;
|
||||
return domReady((function(_this) {
|
||||
return function() {
|
||||
var fontName;
|
||||
return testFonts((function() {
|
||||
var j, len, results;
|
||||
results = [];
|
||||
for (j = 0, len = someCommonFontNames.length; j < len; j++) {
|
||||
fontName = someCommonFontNames[j];
|
||||
results.push(new Font(fontName));
|
||||
}
|
||||
return results;
|
||||
})());
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
testFonts = function(fonts) {
|
||||
var i, testingFonts;
|
||||
fontAvailabilityChecker.init();
|
||||
i = 0;
|
||||
return testingFonts = every(20, function() {
|
||||
var available, callback, font, j, k, l, len, len1, ref, ref1;
|
||||
for (j = 0; j <= 5; j++) {
|
||||
font = fonts[i];
|
||||
available = fontAvailabilityChecker.check(font);
|
||||
if (available) {
|
||||
testedFonts.push(font);
|
||||
ref = FD.each.callbacks;
|
||||
for (k = 0, len = ref.length; k < len; k++) {
|
||||
callback = ref[k];
|
||||
callback(font);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
if (i >= fonts.length) {
|
||||
testingFonts.stop();
|
||||
ref1 = FD.all.callbacks;
|
||||
for (l = 0, len1 = ref1.length; l < len1; l++) {
|
||||
callback = ref1[l];
|
||||
callback(testedFonts);
|
||||
}
|
||||
FD.all.callbacks = [];
|
||||
FD.each.callbacks = [];
|
||||
doneTestingFonts = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* FontDetective.preload()
|
||||
* Starts detecting fonts early
|
||||
*/
|
||||
FD.preload = loadFonts;
|
||||
|
||||
/*
|
||||
* FontDetective.each(function(font){})
|
||||
* Calls back with a `Font` every time a font is detected and tested
|
||||
*/
|
||||
FD.each = function(callback) {
|
||||
var font, j, len;
|
||||
for (j = 0, len = testedFonts.length; j < len; j++) {
|
||||
font = testedFonts[j];
|
||||
callback(font);
|
||||
}
|
||||
if (!doneTestingFonts) {
|
||||
FD.each.callbacks.push(callback);
|
||||
return loadFonts();
|
||||
}
|
||||
};
|
||||
FD.each.callbacks = [];
|
||||
|
||||
/*
|
||||
* FontDetective.all(function(fonts){})
|
||||
* Calls back with an `Array` of `Font`s when all fonts are detected and tested
|
||||
*/
|
||||
FD.all = function(callback) {
|
||||
if (doneTestingFonts) {
|
||||
return callback(testedFonts);
|
||||
} else {
|
||||
FD.all.callbacks.push(callback);
|
||||
return loadFonts();
|
||||
}
|
||||
};
|
||||
return FD.all.callbacks = [];
|
||||
})(window);
|
||||
|
||||
|
||||
},{}]},{},[1]);
|
||||
3
static/html/jspaint/lib/gif.js/gif.js
Normal file
3
static/html/jspaint/lib/gif.js/gif.js
Normal file
File diff suppressed because one or more lines are too long
1
static/html/jspaint/lib/gif.js/gif.js.map
Normal file
1
static/html/jspaint/lib/gif.js/gif.js.map
Normal file
File diff suppressed because one or more lines are too long
3
static/html/jspaint/lib/gif.js/gif.worker.js
Normal file
3
static/html/jspaint/lib/gif.js/gif.worker.js
Normal file
File diff suppressed because one or more lines are too long
1
static/html/jspaint/lib/gif.js/gif.worker.js.map
Normal file
1
static/html/jspaint/lib/gif.js/gif.worker.js.map
Normal file
File diff suppressed because one or more lines are too long
1203
static/html/jspaint/lib/imagetracer_v1.2.5.js
Normal file
1203
static/html/jspaint/lib/imagetracer_v1.2.5.js
Normal file
File diff suppressed because it is too large
Load Diff
2
static/html/jspaint/lib/jquery-3.4.1.min.js
vendored
Normal file
2
static/html/jspaint/lib/jquery-3.4.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
44
static/html/jspaint/lib/konami.js
Normal file
44
static/html/jspaint/lib/konami.js
Normal file
@@ -0,0 +1,44 @@
|
||||
var Konami = {};
|
||||
|
||||
(function() {
|
||||
var afterSequence = function(sequence, action) {
|
||||
var index = 0;
|
||||
|
||||
return function(event) {
|
||||
var matchedKey = event.keyCode === sequence[index];
|
||||
// if it didn't match, reset and try matching against the first key
|
||||
if (!matchedKey) {
|
||||
index = 0;
|
||||
matchedKey = event.keyCode === sequence[index];
|
||||
}
|
||||
|
||||
if (matchedKey) {
|
||||
index += 1;
|
||||
|
||||
// fix for Firefox with "Search for text when you start typing" enabled
|
||||
// https://support.mozilla.org/en-US/kb/search-contents-current-page-text-or-links
|
||||
// prevent the default (opening Quick Search) for B and A,
|
||||
// which are luckily at the end of the Konami Code sequence
|
||||
// (otherwise it could prevent typing A and B in text fields unwantedly)
|
||||
if (event.keyCode === 66 || event.keyCode === 65) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (index === sequence.length) {
|
||||
|
||||
// reset when sequence completed
|
||||
index = 0;
|
||||
|
||||
// fire action
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
Konami.code = function(action) {
|
||||
return afterSequence([38, 38, 40, 40, 37, 39, 37, 39, 66, 65], action);
|
||||
};
|
||||
|
||||
}());
|
||||
66
static/html/jspaint/lib/libtess.min.js
vendored
Normal file
66
static/html/jspaint/lib/libtess.min.js
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Copyright 2000, Silicon Graphics, Inc. All Rights Reserved.
|
||||
Copyright 2015, Google Inc. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice including the dates of first publication and
|
||||
either this permission notice or a reference to http://oss.sgi.com/projects/FreeB/
|
||||
shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Original Code. The Original Code is: OpenGL Sample Implementation,
|
||||
Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
|
||||
Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
|
||||
Copyright in any portions created by third parties is as indicated
|
||||
elsewhere herein. All Rights Reserved.
|
||||
*/
|
||||
|
||||
// wrapper added because of https://github.com/brendankenny/libtess.js/issues/15
|
||||
var libtess=(function() {
|
||||
|
||||
'use strict';var n;function t(a,b){return a.b===b.b&&a.a===b.a}function u(a,b){return a.b<b.b||a.b===b.b&&a.a<=b.a}function v(a,b,c){var d=b.b-a.b,e=c.b-b.b;return 0<d+e?d<e?b.a-a.a+d/(d+e)*(a.a-c.a):b.a-c.a+e/(d+e)*(c.a-a.a):0}function x(a,b,c){var d=b.b-a.b,e=c.b-b.b;return 0<d+e?(b.a-c.a)*d+(b.a-a.a)*e:0}function z(a,b){return a.a<b.a||a.a===b.a&&a.b<=b.b}function aa(a,b,c){var d=b.a-a.a,e=c.a-b.a;return 0<d+e?d<e?b.b-a.b+d/(d+e)*(a.b-c.b):b.b-c.b+e/(d+e)*(c.b-a.b):0}
|
||||
function ba(a,b,c){var d=b.a-a.a,e=c.a-b.a;return 0<d+e?(b.b-c.b)*d+(b.b-a.b)*e:0}function ca(a){return u(a.b.a,a.a)}function da(a){return u(a.a,a.b.a)}function A(a,b,c,d){a=0>a?0:a;c=0>c?0:c;return a<=c?0===c?(b+d)/2:b+a/(a+c)*(d-b):d+c/(a+c)*(b-d)};function ea(a){var b=B(a.b);C(b,a.c);C(b.b,a.c);D(b,a.a);return b}function E(a,b){var c=!1,d=!1;a!==b&&(b.a!==a.a&&(d=!0,F(b.a,a.a)),b.d!==a.d&&(c=!0,G(b.d,a.d)),H(b,a),d||(C(b,a.a),a.a.c=a),c||(D(b,a.d),a.d.a=a))}function I(a){var b=a.b,c=!1;a.d!==a.b.d&&(c=!0,G(a.d,a.b.d));a.c===a?F(a.a,null):(a.b.d.a=J(a),a.a.c=a.c,H(a,J(a)),c||D(a,a.d));b.c===b?(F(b.a,null),G(b.d,null)):(a.d.a=J(b),b.a.c=b.c,H(b,J(b)));fa(a)}
|
||||
function K(a){var b=B(a),c=b.b;H(b,a.e);b.a=a.b.a;C(c,b.a);b.d=c.d=a.d;b=b.b;H(a.b,J(a.b));H(a.b,b);a.b.a=b.a;b.b.a.c=b.b;b.b.d=a.b.d;b.f=a.f;b.b.f=a.b.f;return b}function L(a,b){var c=!1,d=B(a),e=d.b;b.d!==a.d&&(c=!0,G(b.d,a.d));H(d,a.e);H(e,b);d.a=a.b.a;e.a=b.a;d.d=e.d=a.d;a.d.a=e;c||D(d,a.d);return d}function B(a){var b=new M,c=new M,d=a.b.h;c.h=d;d.b.h=b;b.h=a;a.b.h=c;b.b=c;b.c=b;b.e=c;c.b=b;c.c=c;return c.e=b}function H(a,b){var c=a.c,d=b.c;c.b.e=b;d.b.e=a;a.c=d;b.c=c}
|
||||
function C(a,b){var c=b.f,d=new N(b,c);c.e=d;b.f=d;c=d.c=a;do c.a=d,c=c.c;while(c!==a)}function D(a,b){var c=b.d,d=new ga(b,c);c.b=d;b.d=d;d.a=a;d.c=b.c;c=a;do c.d=d,c=c.e;while(c!==a)}function fa(a){var b=a.h;a=a.b.h;b.b.h=a;a.b.h=b}function F(a,b){var c=a.c,d=c;do d.a=b,d=d.c;while(d!==c);c=a.f;d=a.e;d.f=c;c.e=d}function G(a,b){var c=a.a,d=c;do d.d=b,d=d.e;while(d!==c);c=a.d;d=a.b;d.d=c;c.b=d};function ha(a){var b=0;Math.abs(a[1])>Math.abs(a[0])&&(b=1);Math.abs(a[2])>Math.abs(a[b])&&(b=2);return b};var O=4*1E150;function P(a,b){a.f+=b.f;a.b.f+=b.b.f}function ia(a,b,c){a=a.a;b=b.a;c=c.a;if(b.b.a===a)return c.b.a===a?u(b.a,c.a)?0>=x(c.b.a,b.a,c.a):0<=x(b.b.a,c.a,b.a):0>=x(c.b.a,a,c.a);if(c.b.a===a)return 0<=x(b.b.a,a,b.a);b=v(b.b.a,a,b.a);a=v(c.b.a,a,c.a);return b>=a}function Q(a){a.a.i=null;var b=a.e;b.a.c=b.c;b.c.a=b.a;a.e=null}function ja(a,b){I(a.a);a.c=!1;a.a=b;b.i=a}function ka(a){var b=a.a.a;do a=R(a);while(a.a.a===b);a.c&&(b=L(S(a).a.b,a.a.e),ja(a,b),a=R(a));return a}
|
||||
function la(a,b,c){var d=new ma;d.a=c;d.e=na(a.f,b.e,d);return c.i=d}function oa(a,b){switch(a.s){case 100130:return 0!==(b&1);case 100131:return 0!==b;case 100132:return 0<b;case 100133:return 0>b;case 100134:return 2<=b||-2>=b}return!1}function pa(a){var b=a.a,c=b.d;c.c=a.d;c.a=b;Q(a)}function T(a,b,c){a=b;for(b=b.a;a!==c;){a.c=!1;var d=S(a),e=d.a;if(e.a!==b.a){if(!d.c){pa(a);break}e=L(b.c.b,e.b);ja(d,e)}b.c!==e&&(E(J(e),e),E(b,e));pa(a);b=d.a;a=d}return b}
|
||||
function U(a,b,c,d,e,f){var g=!0;do la(a,b,c.b),c=c.c;while(c!==d);for(null===e&&(e=S(b).a.b.c);;){d=S(b);c=d.a.b;if(c.a!==e.a)break;c.c!==e&&(E(J(c),c),E(J(e),c));d.f=b.f-c.f;d.d=oa(a,d.f);b.b=!0;!g&&qa(a,b)&&(P(c,e),Q(b),I(e));g=!1;b=d;e=c}b.b=!0;f&&ra(a,b)}function sa(a,b,c,d,e){var f=[b.g[0],b.g[1],b.g[2]];b.d=null;b.d=a.o?a.o(f,c,d,a.c)||null:null;null===b.d&&(e?a.n||(V(a,100156),a.n=!0):b.d=c[0])}
|
||||
function ta(a,b,c){var d=[null,null,null,null];d[0]=b.a.d;d[1]=c.a.d;sa(a,b.a,d,[.5,.5,0,0],!1);E(b,c)}function ua(a,b,c,d,e){var f=Math.abs(b.b-a.b)+Math.abs(b.a-a.a),g=Math.abs(c.b-a.b)+Math.abs(c.a-a.a),h=e+1;d[e]=.5*g/(f+g);d[h]=.5*f/(f+g);a.g[0]+=d[e]*b.g[0]+d[h]*c.g[0];a.g[1]+=d[e]*b.g[1]+d[h]*c.g[1];a.g[2]+=d[e]*b.g[2]+d[h]*c.g[2]}
|
||||
function qa(a,b){var c=S(b),d=b.a,e=c.a;if(u(d.a,e.a)){if(0<x(e.b.a,d.a,e.a))return!1;if(!t(d.a,e.a))K(e.b),E(d,J(e)),b.b=c.b=!0;else if(d.a!==e.a){var c=a.e,f=d.a.h;if(0<=f){var c=c.b,g=c.d,h=c.e,k=c.c,l=k[f];g[l]=g[c.a];k[g[l]]=l;l<=--c.a&&(1>=l?W(c,l):u(h[g[l>>1]],h[g[l]])?W(c,l):va(c,l));h[f]=null;k[f]=c.b;c.b=f}else for(c.c[-(f+1)]=null;0<c.a&&null===c.c[c.d[c.a-1]];)--c.a;ta(a,J(e),d)}}else{if(0>x(d.b.a,e.a,d.a))return!1;R(b).b=b.b=!0;K(d.b);E(J(e),d)}return!0}
|
||||
function wa(a,b){var c=S(b),d=b.a,e=c.a,f=d.a,g=e.a,h=d.b.a,k=e.b.a,l=new N;x(h,a.a,f);x(k,a.a,g);if(f===g||Math.min(f.a,h.a)>Math.max(g.a,k.a))return!1;if(u(f,g)){if(0<x(k,f,g))return!1}else if(0>x(h,g,f))return!1;var r=h,p=f,q=k,y=g,m,w;u(r,p)||(m=r,r=p,p=m);u(q,y)||(m=q,q=y,y=m);u(r,q)||(m=r,r=q,q=m,m=p,p=y,y=m);u(q,p)?u(p,y)?(m=v(r,q,p),w=v(q,p,y),0>m+w&&(m=-m,w=-w),l.b=A(m,q.b,w,p.b)):(m=x(r,q,p),w=-x(r,y,p),0>m+w&&(m=-m,w=-w),l.b=A(m,q.b,w,y.b)):l.b=(q.b+p.b)/2;z(r,p)||(m=r,r=p,p=m);z(q,y)||
|
||||
(m=q,q=y,y=m);z(r,q)||(m=r,r=q,q=m,m=p,p=y,y=m);z(q,p)?z(p,y)?(m=aa(r,q,p),w=aa(q,p,y),0>m+w&&(m=-m,w=-w),l.a=A(m,q.a,w,p.a)):(m=ba(r,q,p),w=-ba(r,y,p),0>m+w&&(m=-m,w=-w),l.a=A(m,q.a,w,y.a)):l.a=(q.a+p.a)/2;u(l,a.a)&&(l.b=a.a.b,l.a=a.a.a);r=u(f,g)?f:g;u(r,l)&&(l.b=r.b,l.a=r.a);if(t(l,f)||t(l,g))return qa(a,b),!1;if(!t(h,a.a)&&0<=x(h,a.a,l)||!t(k,a.a)&&0>=x(k,a.a,l)){if(k===a.a)return K(d.b),E(e.b,d),b=ka(b),d=S(b).a,T(a,S(b),c),U(a,b,J(d),d,d,!0),!0;if(h===a.a){K(e.b);E(d.e,J(e));f=c=b;g=f.a.b.a;
|
||||
do f=R(f);while(f.a.b.a===g);b=f;f=S(b).a.b.c;c.a=J(e);e=T(a,c,null);U(a,b,e.c,d.b.c,f,!0);return!0}0<=x(h,a.a,l)&&(R(b).b=b.b=!0,K(d.b),d.a.b=a.a.b,d.a.a=a.a.a);0>=x(k,a.a,l)&&(b.b=c.b=!0,K(e.b),e.a.b=a.a.b,e.a.a=a.a.a);return!1}K(d.b);K(e.b);E(J(e),d);d.a.b=l.b;d.a.a=l.a;d.a.h=xa(a.e,d.a);d=d.a;e=[0,0,0,0];l=[f.d,h.d,g.d,k.d];d.g[0]=d.g[1]=d.g[2]=0;ua(d,f,h,e,0);ua(d,g,k,e,2);sa(a,d,l,e,!0);R(b).b=b.b=c.b=!0;return!1}
|
||||
function ra(a,b){for(var c=S(b);;){for(;c.b;)b=c,c=S(c);if(!b.b&&(c=b,b=R(b),null===b||!b.b))break;b.b=!1;var d=b.a,e=c.a,f;if(f=d.b.a!==e.b.a)a:{f=b;var g=S(f),h=f.a,k=g.a,l=void 0;if(u(h.b.a,k.b.a)){if(0>x(h.b.a,k.b.a,h.a)){f=!1;break a}R(f).b=f.b=!0;l=K(h);E(k.b,l);l.d.c=f.d}else{if(0<x(k.b.a,h.b.a,k.a)){f=!1;break a}f.b=g.b=!0;l=K(k);E(h.e,k.b);l.b.d.c=f.d}f=!0}f&&(c.c?(Q(c),I(e),c=S(b),e=c.a):b.c&&(Q(b),I(d),b=R(c),d=b.a));if(d.a!==e.a)if(d.b.a===e.b.a||b.c||c.c||d.b.a!==a.a&&e.b.a!==a.a)qa(a,
|
||||
b);else if(wa(a,b))break;d.a===e.a&&d.b.a===e.b.a&&(P(e,d),Q(b),I(d),b=R(c))}}
|
||||
function ya(a,b){a.a=b;for(var c=b.c;null===c.i;)if(c=c.c,c===b.c){var c=a,d=b,e=new ma;e.a=d.c.b;var f=c.f,g=f.a;do g=g.a;while(null!==g.b&&!f.c(f.b,e,g.b));var f=g.b,h=S(f),e=f.a,g=h.a;if(0===x(e.b.a,d,e.a))e=f.a,t(e.a,d)||t(e.b.a,d)||(K(e.b),f.c&&(I(e.c),f.c=!1),E(d.c,e),ya(c,d));else{var k=u(g.b.a,e.b.a)?f:h,h=void 0;f.d||k.c?(k===f?h=L(d.c.b,e.e):h=L(g.b.c.b,d.c).b,k.c?ja(k,h):(e=c,f=la(c,f,h),f.f=R(f).f+f.a.f,f.d=oa(e,f.f)),ya(c,d)):U(c,f,d.c,d.c,null,!0)}return}c=ka(c.i);e=S(c);f=e.a;e=T(a,
|
||||
e,null);if(e.c===f){var f=e,e=f.c,g=S(c),h=c.a,k=g.a,l=!1;h.b.a!==k.b.a&&wa(a,c);t(h.a,a.a)&&(E(J(e),h),c=ka(c),e=S(c).a,T(a,S(c),g),l=!0);t(k.a,a.a)&&(E(f,J(k)),f=T(a,g,null),l=!0);l?U(a,c,f.c,e,e,!0):(u(k.a,h.a)?d=J(k):d=h,d=L(f.c.b,d),U(a,c,d,d.c,d.c,!1),d.b.i.c=!0,ra(a,c))}else U(a,c,e.c,f,f,!0)}function za(a,b){var c=new ma,d=ea(a.b);d.a.b=O;d.a.a=b;d.b.a.b=-O;d.b.a.a=b;a.a=d.b.a;c.a=d;c.f=0;c.d=!1;c.c=!1;c.h=!0;c.b=!1;d=a.f;d=na(d,d.a,c);c.e=d};function Aa(a){this.a=new Ba;this.b=a;this.c=ia}function na(a,b,c){do b=b.c;while(null!==b.b&&!a.c(a.b,b.b,c));a=new Ba(c,b.a,b);b.a.c=a;return b.a=a};function Ba(a,b,c){this.b=a||null;this.a=b||this;this.c=c||this};function X(){this.d=Y;this.p=this.b=this.q=null;this.j=[0,0,0];this.s=100130;this.n=!1;this.o=this.a=this.e=this.f=null;this.m=!1;this.c=this.r=this.i=this.k=this.l=this.h=null}var Y=0;n=X.prototype;n.x=function(){Z(this,Y)};n.B=function(a,b){switch(a){case 100142:return;case 100140:switch(b){case 100130:case 100131:case 100132:case 100133:case 100134:this.s=b;return}break;case 100141:this.m=!!b;return;default:V(this,100900);return}V(this,100901)};
|
||||
n.y=function(a){switch(a){case 100142:return 0;case 100140:return this.s;case 100141:return this.m;default:V(this,100900)}return!1};n.A=function(a,b,c){this.j[0]=a;this.j[1]=b;this.j[2]=c};
|
||||
n.z=function(a,b){var c=b?b:null;switch(a){case 100100:case 100106:this.h=c;break;case 100104:case 100110:this.l=c;break;case 100101:case 100107:this.k=c;break;case 100102:case 100108:this.i=c;break;case 100103:case 100109:this.p=c;break;case 100105:case 100111:this.o=c;break;case 100112:this.r=c;break;default:V(this,100900)}};
|
||||
n.C=function(a,b){var c=!1,d=[0,0,0];Z(this,2);for(var e=0;3>e;++e){var f=a[e];-1E150>f&&(f=-1E150,c=!0);1E150<f&&(f=1E150,c=!0);d[e]=f}c&&V(this,100155);c=this.q;null===c?(c=ea(this.b),E(c,c.b)):(K(c),c=c.e);c.a.d=b;c.a.g[0]=d[0];c.a.g[1]=d[1];c.a.g[2]=d[2];c.f=1;c.b.f=-1;this.q=c};n.u=function(a){Z(this,Y);this.d=1;this.b=new Ca;this.c=a};n.t=function(){Z(this,1);this.d=2;this.q=null};n.v=function(){Z(this,2);this.d=1};
|
||||
n.w=function(){Z(this,1);this.d=Y;var a=this.j[0],b=this.j[1],c=this.j[2],d=!1,e=[a,b,c];if(0===a&&0===b&&0===c){for(var b=[-2*1E150,-2*1E150,-2*1E150],f=[2*1E150,2*1E150,2*1E150],c=[],g=[],d=this.b.c,a=d.e;a!==d;a=a.e)for(var h=0;3>h;++h){var k=a.g[h];k<f[h]&&(f[h]=k,g[h]=a);k>b[h]&&(b[h]=k,c[h]=a)}a=0;b[1]-f[1]>b[0]-f[0]&&(a=1);b[2]-f[2]>b[a]-f[a]&&(a=2);if(f[a]>=b[a])e[0]=0,e[1]=0,e[2]=1;else{b=0;f=g[a];c=c[a];g=[0,0,0];f=[f.g[0]-c.g[0],f.g[1]-c.g[1],f.g[2]-c.g[2]];h=[0,0,0];for(a=d.e;a!==d;a=
|
||||
a.e)h[0]=a.g[0]-c.g[0],h[1]=a.g[1]-c.g[1],h[2]=a.g[2]-c.g[2],g[0]=f[1]*h[2]-f[2]*h[1],g[1]=f[2]*h[0]-f[0]*h[2],g[2]=f[0]*h[1]-f[1]*h[0],k=g[0]*g[0]+g[1]*g[1]+g[2]*g[2],k>b&&(b=k,e[0]=g[0],e[1]=g[1],e[2]=g[2]);0>=b&&(e[0]=e[1]=e[2]=0,e[ha(f)]=1)}d=!0}g=ha(e);a=this.b.c;b=(g+1)%3;c=(g+2)%3;g=0<e[g]?1:-1;for(e=a.e;e!==a;e=e.e)e.b=e.g[b],e.a=g*e.g[c];if(d){e=0;d=this.b.a;for(a=d.b;a!==d;a=a.b)if(b=a.a,!(0>=b.f)){do e+=(b.a.b-b.b.a.b)*(b.a.a+b.b.a.a),b=b.e;while(b!==a.a)}if(0>e)for(e=this.b.c,d=e.e;d!==
|
||||
e;d=d.e)d.a=-d.a}this.n=!1;e=this.b.b;for(a=e.h;a!==e;a=d)if(d=a.h,b=a.e,t(a.a,a.b.a)&&a.e.e!==a&&(ta(this,b,a),I(a),a=b,b=a.e),b.e===a){if(b!==a){if(b===d||b===d.b)d=d.h;I(b)}if(a===d||a===d.b)d=d.h;I(a)}this.e=e=new Da;d=this.b.c;for(a=d.e;a!==d;a=a.e)a.h=xa(e,a);Ea(e);this.f=new Aa(this);za(this,-O);for(za(this,O);null!==(e=Fa(this.e));){for(;;){a:if(a=this.e,0===a.a)d=Ga(a.b);else if(d=a.c[a.d[a.a-1]],0!==a.b.a&&(a=Ga(a.b),u(a,d))){d=a;break a}if(null===d||!t(d,e))break;d=Fa(this.e);ta(this,e.c,
|
||||
d.c)}ya(this,e)}this.a=this.f.a.a.b.a.a;for(e=0;null!==(d=this.f.a.a.b);)d.h||++e,Q(d);this.f=null;e=this.e;e.b=null;e.d=null;this.e=e.c=null;e=this.b;for(a=e.a.b;a!==e.a;a=d)d=a.b,a=a.a,a.e.e===a&&(P(a.c,a),I(a));if(!this.n){e=this.b;if(this.m)for(a=e.b.h;a!==e.b;a=d)d=a.h,a.b.d.c!==a.d.c?a.f=a.d.c?1:-1:I(a);else for(a=e.a.b;a!==e.a;a=d)if(d=a.b,a.c){for(a=a.a;u(a.b.a,a.a);a=a.c.b);for(;u(a.a,a.b.a);a=a.e);b=a.c.b;for(c=void 0;a.e!==b;)if(u(a.b.a,b.a)){for(;b.e!==a&&(ca(b.e)||0>=x(b.a,b.b.a,b.e.b.a));)c=
|
||||
L(b.e,b),b=c.b;b=b.c.b}else{for(;b.e!==a&&(da(a.c.b)||0<=x(a.b.a,a.a,a.c.b.a));)c=L(a,a.c.b),a=c.b;a=a.e}for(;b.e.e!==a;)c=L(b.e,b),b=c.b}if(this.h||this.i||this.k||this.l)if(this.m)for(e=this.b,d=e.a.b;d!==e.a;d=d.b){if(d.c){this.h&&this.h(2,this.c);a=d.a;do this.k&&this.k(a.a.d,this.c),a=a.e;while(a!==d.a);this.i&&this.i(this.c)}}else{e=this.b;d=!!this.l;a=!1;b=-1;for(c=e.a.d;c!==e.a;c=c.d)if(c.c){a||(this.h&&this.h(4,this.c),a=!0);g=c.a;do d&&(f=g.b.d.c?0:1,b!==f&&(b=f,this.l&&this.l(!!b,this.c))),
|
||||
this.k&&this.k(g.a.d,this.c),g=g.e;while(g!==c.a)}a&&this.i&&this.i(this.c)}if(this.r){e=this.b;for(a=e.a.b;a!==e.a;a=d)if(d=a.b,!a.c){b=a.a;c=b.e;g=void 0;do g=c,c=g.e,g.d=null,null===g.b.d&&(g.c===g?F(g.a,null):(g.a.c=g.c,H(g,J(g))),f=g.b,f.c===f?F(f.a,null):(f.a.c=f.c,H(f,J(f))),fa(g));while(g!==b);b=a.d;a=a.b;a.d=b;b.b=a}this.r(this.b);this.c=this.b=null;return}}this.b=this.c=null};
|
||||
function Z(a,b){if(a.d!==b)for(;a.d!==b;)if(a.d<b)switch(a.d){case Y:V(a,100151);a.u(null);break;case 1:V(a,100152),a.t()}else switch(a.d){case 2:V(a,100154);a.v();break;case 1:V(a,100153),a.w()}}function V(a,b){a.p&&a.p(b,a.c)};function ga(a,b){this.b=a||this;this.d=b||this;this.a=null;this.c=!1};function M(){this.h=this;this.i=this.d=this.a=this.e=this.c=this.b=null;this.f=0}function J(a){return a.b.e};function Ca(){this.c=new N;this.a=new ga;this.b=new M;this.d=new M;this.b.b=this.d;this.d.b=this.b};function N(a,b){this.e=a||this;this.f=b||this;this.d=this.c=null;this.g=[0,0,0];this.h=this.a=this.b=0};function Da(){this.c=[];this.d=null;this.a=0;this.e=!1;this.b=new Ha}function Ea(a){a.d=[];for(var b=0;b<a.a;b++)a.d[b]=b;a.d.sort(function(a){return function(b,e){return u(a[b],a[e])?1:-1}}(a.c));a.e=!0;Ia(a.b)}function xa(a,b){if(a.e){var c=a.b,d=++c.a;2*d>c.f&&(c.f*=2,c.c=Ja(c.c,c.f+1));var e;0===c.b?e=d:(e=c.b,c.b=c.c[c.b]);c.e[e]=b;c.c[e]=d;c.d[d]=e;c.h&&va(c,d);return e}c=a.a++;a.c[c]=b;return-(c+1)}
|
||||
function Fa(a){if(0===a.a)return Ka(a.b);var b=a.c[a.d[a.a-1]];if(0!==a.b.a&&u(Ga(a.b),b))return Ka(a.b);do--a.a;while(0<a.a&&null===a.c[a.d[a.a-1]]);return b};function Ha(){this.d=Ja([0],33);this.e=[null,null];this.c=[0,0];this.a=0;this.f=32;this.b=0;this.h=!1;this.d[1]=1}function Ja(a,b){for(var c=Array(b),d=0;d<a.length;d++)c[d]=a[d];for(;d<b;d++)c[d]=0;return c}function Ia(a){for(var b=a.a;1<=b;--b)W(a,b);a.h=!0}function Ga(a){return a.e[a.d[1]]}function Ka(a){var b=a.d,c=a.e,d=a.c,e=b[1],f=c[e];0<a.a&&(b[1]=b[a.a],d[b[1]]=1,c[e]=null,d[e]=a.b,a.b=e,0<--a.a&&W(a,1));return f}
|
||||
function W(a,b){for(var c=a.d,d=a.e,e=a.c,f=b,g=c[f];;){var h=f<<1;h<a.a&&u(d[c[h+1]],d[c[h]])&&(h+=1);var k=c[h];if(h>a.a||u(d[g],d[k])){c[f]=g;e[g]=f;break}c[f]=k;e[k]=f;f=h}}function va(a,b){for(var c=a.d,d=a.e,e=a.c,f=b,g=c[f];;){var h=f>>1,k=c[h];if(0===h||u(d[k],d[g])){c[f]=g;e[g]=f;break}c[f]=k;e[k]=f;f=h}};function ma(){this.e=this.a=null;this.f=0;this.c=this.b=this.h=this.d=!1}function S(a){return a.e.c.b}function R(a){return a.e.a.b};this.libtess={GluTesselator:X,windingRule:{GLU_TESS_WINDING_ODD:100130,GLU_TESS_WINDING_NONZERO:100131,GLU_TESS_WINDING_POSITIVE:100132,GLU_TESS_WINDING_NEGATIVE:100133,GLU_TESS_WINDING_ABS_GEQ_TWO:100134},primitiveType:{GL_LINE_LOOP:2,GL_TRIANGLES:4,GL_TRIANGLE_STRIP:5,GL_TRIANGLE_FAN:6},errorType:{GLU_TESS_MISSING_BEGIN_POLYGON:100151,GLU_TESS_MISSING_END_POLYGON:100153,GLU_TESS_MISSING_BEGIN_CONTOUR:100152,GLU_TESS_MISSING_END_CONTOUR:100154,GLU_TESS_COORD_TOO_LARGE:100155,GLU_TESS_NEED_COMBINE_CALLBACK:100156},
|
||||
gluEnum:{GLU_TESS_MESH:100112,GLU_TESS_TOLERANCE:100142,GLU_TESS_WINDING_RULE:100140,GLU_TESS_BOUNDARY_ONLY:100141,GLU_INVALID_ENUM:100900,GLU_INVALID_VALUE:100901,GLU_TESS_BEGIN:100100,GLU_TESS_VERTEX:100101,GLU_TESS_END:100102,GLU_TESS_ERROR:100103,GLU_TESS_EDGE_FLAG:100104,GLU_TESS_COMBINE:100105,GLU_TESS_BEGIN_DATA:100106,GLU_TESS_VERTEX_DATA:100107,GLU_TESS_END_DATA:100108,GLU_TESS_ERROR_DATA:100109,GLU_TESS_EDGE_FLAG_DATA:100110,GLU_TESS_COMBINE_DATA:100111}};X.prototype.gluDeleteTess=X.prototype.x;
|
||||
X.prototype.gluTessProperty=X.prototype.B;X.prototype.gluGetTessProperty=X.prototype.y;X.prototype.gluTessNormal=X.prototype.A;X.prototype.gluTessCallback=X.prototype.z;X.prototype.gluTessVertex=X.prototype.C;X.prototype.gluTessBeginPolygon=X.prototype.u;X.prototype.gluTessBeginContour=X.prototype.t;X.prototype.gluTessEndContour=X.prototype.v;X.prototype.gluTessEndPolygon=X.prototype.w; if (typeof module !== 'undefined') { module.exports = this.libtess; }
|
||||
|
||||
// wrapper added because of https://github.com/brendankenny/libtess.js/issues/15
|
||||
return this.libtess;
|
||||
}).apply(new Object()); // need to provide a valid "this" due to strict mode; simply use a dummy object
|
||||
1653
static/html/jspaint/lib/os-gui/$Window.js
Normal file
1653
static/html/jspaint/lib/os-gui/$Window.js
Normal file
File diff suppressed because it is too large
Load Diff
996
static/html/jspaint/lib/os-gui/MenuBar.js
Normal file
996
static/html/jspaint/lib/os-gui/MenuBar.js
Normal file
@@ -0,0 +1,996 @@
|
||||
((exports) => {
|
||||
|
||||
function E(nodeName, attrs) {
|
||||
const el = document.createElement(nodeName);
|
||||
if (attrs) {
|
||||
for (const key in attrs) {
|
||||
if (key === "class") {
|
||||
el.className = attrs[key];
|
||||
} else {
|
||||
el.setAttribute(key, attrs[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return el;
|
||||
}
|
||||
|
||||
let uid_counter = 0;
|
||||
function uid() {
|
||||
// make id from counter (guaranteeing page-local uniqueness)
|
||||
// and random base 36 number (making it look random, so there's no temptation to use it as a sequence)
|
||||
// Note: Math.random().toString(36).slice(2) can give empty string
|
||||
return (uid_counter++).toString(36) + Math.random().toString(36).slice(2);
|
||||
}
|
||||
|
||||
// @TODO: export hotkey helpers; also include one for escaping &'s (useful for dynamic menus like a list of history entries)
|
||||
// also @TODO: support dynamic menus (e.g. a list of history entries, contextually shown options, or a contextually named "Undo <action>" label; Explorer has all these things)
|
||||
|
||||
// & defines accelerators (hotkeys) in menus and buttons and things, which get underlined in the UI.
|
||||
// & can be escaped by doubling it, e.g. "&Taskbar && Start Menu"
|
||||
function index_of_hotkey(text) {
|
||||
// Returns the index of the ampersand that defines a hotkey, or -1 if not present.
|
||||
|
||||
// return english_text.search(/(?<!&)&(?!&|\s)/); // not enough browser support for negative lookbehind assertions
|
||||
|
||||
// The space here handles beginning-of-string matching and counteracts the offset for the [^&] so it acts like a negative lookbehind
|
||||
return ` ${text}`.search(/[^&]&[^&\s]/);
|
||||
}
|
||||
// function has_hotkey(text) {
|
||||
// return index_of_hotkey(text) !== -1;
|
||||
// }
|
||||
function remove_hotkey(text) {
|
||||
return text.replace(/\s?\(&.\)/, "").replace(/([^&]|^)&([^&\s])/, "$1$2");
|
||||
}
|
||||
function display_hotkey(text) {
|
||||
// TODO: use a more general term like .hotkey or .accelerator?
|
||||
return text.replace(/([^&]|^)&([^&\s])/, "$1<span class='menu-hotkey'>$2</span>").replace(/&&/g, "&");
|
||||
}
|
||||
function get_hotkey(text) {
|
||||
return text[index_of_hotkey(text) + 1].toUpperCase();
|
||||
}
|
||||
|
||||
// TODO: support copy/pasting text in the text tool textarea from the menus
|
||||
// probably by recording document.activeElement on pointer down,
|
||||
// and restoring focus before executing menu item actions.
|
||||
|
||||
const MENU_DIVIDER = "MENU_DIVIDER";
|
||||
|
||||
const MAX_MENU_NESTING = 1000;
|
||||
|
||||
let internal_z_counter = 1;
|
||||
function get_new_menu_z_index() {
|
||||
// integrate with the OS window z-indexes, if applicable
|
||||
// but don't depend on $Window existing, the modules should be independent
|
||||
if (typeof $Window !== "undefined") {
|
||||
return ($Window.Z_INDEX++) + MAX_MENU_NESTING; // MAX_MENU_NESTING is needed because the window gets brought to the top
|
||||
}
|
||||
return (++internal_z_counter) + MAX_MENU_NESTING;
|
||||
}
|
||||
|
||||
function MenuBar(menus) {
|
||||
if (!(this instanceof MenuBar)) {
|
||||
return new MenuBar(menus);
|
||||
}
|
||||
|
||||
const menus_el = E("div", {
|
||||
class: "menus",
|
||||
role: "menubar",
|
||||
"aria-label": "Application Menu",
|
||||
});
|
||||
menus_el.style.touchAction = "none";
|
||||
menus_el.style.pointerEvents = "none";
|
||||
|
||||
// returns writing/layout direction, "ltr" or "rtl"
|
||||
function get_direction() {
|
||||
return window.get_direction ? window.get_direction() : getComputedStyle(menus_el).direction;
|
||||
}
|
||||
|
||||
let selecting_menus = false; // state where you can glide between menus without clicking
|
||||
|
||||
const top_level_menus = [];
|
||||
let top_level_menu_index = -1; // index of the top level menu that's most recently open, or highlighted
|
||||
let active_menu_popup; // most nested open MenuPopup
|
||||
const menu_popup_by_el = new WeakMap(); // maps DOM elements to MenuPopup instances
|
||||
|
||||
// There can be multiple menu bars instantiated from the same menu definitions,
|
||||
// so this can't be a map of menu item to submenu, it has to be of menu item ELEMENTS to submenu.
|
||||
// (or you know, it could work totally differently, this is just one way to do it)
|
||||
// This is for entering submenus.
|
||||
const submenu_popup_by_menu_item_el = new WeakMap();
|
||||
|
||||
// This is for exiting submenus.
|
||||
const parent_item_el_by_popup_el = new WeakMap();
|
||||
|
||||
const close_menus = () => {
|
||||
for (const { menu_button_el } of top_level_menus) {
|
||||
if (menu_button_el.getAttribute("aria-expanded") === "true") {
|
||||
menu_button_el.dispatchEvent(new CustomEvent("release"), {});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const refocus_window = () => {
|
||||
const window_el = menus_el.closest(".window");
|
||||
if (window_el) {
|
||||
window_el.dispatchEvent(new CustomEvent("refocus-window"));
|
||||
}
|
||||
};
|
||||
|
||||
const top_level_highlight = (new_index_or_menu_key) => {
|
||||
const new_index = typeof new_index_or_menu_key === "string" ?
|
||||
Object.keys(menus).indexOf(new_index_or_menu_key) :
|
||||
new_index_or_menu_key;
|
||||
if (top_level_menu_index !== -1 && top_level_menu_index !== new_index) {
|
||||
top_level_menus[top_level_menu_index].menu_button_el.classList.remove("highlight");
|
||||
// could close the menu here, but it's handled externally right now
|
||||
}
|
||||
if (new_index !== -1) {
|
||||
top_level_menus[new_index].menu_button_el.classList.add("highlight");
|
||||
}
|
||||
top_level_menu_index = new_index;
|
||||
};
|
||||
menus_el.addEventListener("pointerleave", () => {
|
||||
// unhighlight unless a menu is open
|
||||
if (
|
||||
top_level_menu_index !== -1 &&
|
||||
top_level_menus[top_level_menu_index].menu_popup_el.style.display === "none"
|
||||
) {
|
||||
top_level_highlight(-1);
|
||||
}
|
||||
});
|
||||
|
||||
const is_disabled = item => {
|
||||
if (typeof item.enabled === "function") {
|
||||
return !item.enabled();
|
||||
} else if (typeof item.enabled === "boolean") {
|
||||
return !item.enabled;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function send_info_event(item) {
|
||||
// @TODO: in a future version, give the whole menu item definition (or null)
|
||||
const description = item?.description || "";
|
||||
if (window.jQuery) {
|
||||
// old API (using jQuery's "extraParameters"), made forwards compatible with new API (event.detail)
|
||||
const event = new window.jQuery.Event("info", { detail: { description } });
|
||||
const extraParam = {
|
||||
toString() {
|
||||
console.warn("jQuery extra parameter for info event is deprecated, use event.detail instead");
|
||||
return description;
|
||||
},
|
||||
};
|
||||
window.jQuery(menus_el).trigger(event, extraParam);
|
||||
} else {
|
||||
menus_el.dispatchEvent(new CustomEvent("info", { detail: { description } }));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// attached to menu bar and floating popups (which are not descendants of the menu bar)
|
||||
function handleKeyDown(e) {
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
const active_menu_popup_el = active_menu_popup?.element;
|
||||
const top_level_menu = top_level_menus[top_level_menu_index];
|
||||
const { menu_button_el, open_top_level_menu } = top_level_menu || {};
|
||||
const menu_popup_el = active_menu_popup_el || top_level_menu?.menu_popup_el;
|
||||
const parent_item_el = parent_item_el_by_popup_el.get(active_menu_popup_el);
|
||||
const highlighted_item_el = menu_popup_el?.querySelector(".menu-item.highlight");
|
||||
|
||||
// console.log("keydown", e.key, { target: e.target, active_menu_popup_el, top_level_menu, menu_popup_el, parent_item_el, highlighted_item_el });
|
||||
|
||||
switch (e.key) {
|
||||
case "ArrowLeft":
|
||||
case "ArrowRight":
|
||||
const right = e.key === "ArrowRight";
|
||||
if (
|
||||
highlighted_item_el?.matches(".has-submenu:not([aria-disabled='true'])") &&
|
||||
(get_direction() === "ltr") === right
|
||||
) {
|
||||
// enter submenu
|
||||
highlighted_item_el.click();
|
||||
e.preventDefault();
|
||||
} else if (
|
||||
active_menu_popup &&
|
||||
active_menu_popup.parentMenuPopup && // left/right doesn't make sense to close the top level menu
|
||||
(get_direction() === "ltr") !== right
|
||||
) {
|
||||
// exit submenu
|
||||
active_menu_popup.close(true); // This changes the active_menu_popup_el to the parent menu!
|
||||
parent_item_el.setAttribute("aria-expanded", "false");
|
||||
send_info_event(active_menu_popup.menuItems[active_menu_popup.itemElements.indexOf(parent_item_el)]);
|
||||
e.preventDefault();
|
||||
} else if (
|
||||
// basically any case except if you hover to open a submenu and then press right/left
|
||||
// in which case the menu is already open/focused
|
||||
// This is mimicking the behavior of Explorer's menus; most Windows 98 apps work differently; @TODO: make this configurable
|
||||
highlighted_item_el ||
|
||||
!active_menu_popup ||
|
||||
!active_menu_popup.parentMenuPopup
|
||||
) {
|
||||
// go to next/previous top level menu, wrapping around
|
||||
// and open a new menu only if a menu was already open
|
||||
const menu_was_open = menu_popup_el && menu_popup_el.style.display !== "none";
|
||||
const cycle_dir = ((get_direction() === "ltr") === right) ? 1 : -1;
|
||||
let new_index;
|
||||
if (top_level_menu_index === -1) {
|
||||
new_index = cycle_dir === 1 ? 0 : top_level_menus.length - 1;
|
||||
} else {
|
||||
new_index = (top_level_menu_index + cycle_dir + top_level_menus.length) % top_level_menus.length;
|
||||
}
|
||||
const new_top_level_menu = top_level_menus[new_index];
|
||||
const target_button_el = new_top_level_menu.menu_button_el;
|
||||
if (menu_was_open) {
|
||||
new_top_level_menu.open_top_level_menu("keydown");
|
||||
} else {
|
||||
menu_button_el?.dispatchEvent(new CustomEvent("release"), {});
|
||||
target_button_el.focus({ preventScroll: true });
|
||||
// Note case where menu is closed, menu button is hovered, then menu bar is unhovered,
|
||||
// rehovered (outside any buttons), and unhovered, and THEN you try to go to the next menu.
|
||||
top_level_highlight(new_index);
|
||||
}
|
||||
e.preventDefault();
|
||||
} // else:
|
||||
// if there's no highlighted item, the user may be expecting to enter the menu even though it's already open,
|
||||
// so it makes sense to do nothing (as Windows 98 does) and not go to the next/previous menu
|
||||
// (although highlighting the first item might be nicer...)
|
||||
break;
|
||||
case "ArrowUp":
|
||||
case "ArrowDown":
|
||||
const down = e.key === "ArrowDown";
|
||||
// if (menu_popup_el && menu_popup_el.style.display !== "none") && highlighted_item_el) {
|
||||
if (active_menu_popup) {
|
||||
const cycle_dir = down ? 1 : -1;
|
||||
const item_els = [...menu_popup_el.querySelectorAll(".menu-item")];
|
||||
const from_index = item_els.indexOf(highlighted_item_el);
|
||||
let to_index = (from_index + cycle_dir + item_els.length) % item_els.length;
|
||||
if (from_index === -1) {
|
||||
if (down) {
|
||||
to_index = 0;
|
||||
} else {
|
||||
to_index = item_els.length - 1;
|
||||
}
|
||||
}
|
||||
// more fun way to do it:
|
||||
// const to_index = (Math.max(from_index, -down) + cycle_dir + item_els.length) % item_els.length;
|
||||
|
||||
const to_item_el = item_els[to_index];
|
||||
// active_menu_popup.highlight(to_index); // wouldn't work because to_index doesn't count separators
|
||||
active_menu_popup.highlight(to_item_el);
|
||||
send_info_event(active_menu_popup.menuItems[active_menu_popup.itemElements.indexOf(to_item_el)]);
|
||||
e.preventDefault();
|
||||
} else {
|
||||
open_top_level_menu?.("keydown");
|
||||
}
|
||||
e.preventDefault();
|
||||
break;
|
||||
case "Escape":
|
||||
if (active_menu_popup) {
|
||||
// (@TODO: doesn't parent_item_el always exist?)
|
||||
if (parent_item_el && parent_item_el !== menu_button_el) {
|
||||
// exit submenu (@TODO: DRY further by moving more logic into close()?)
|
||||
active_menu_popup.close(true); // This changes the active_menu_popup to the parent menu!
|
||||
parent_item_el.setAttribute("aria-expanded", "false");
|
||||
send_info_event(active_menu_popup.menuItems[active_menu_popup.itemElements.indexOf(parent_item_el)]);
|
||||
} else {
|
||||
// close_menus takes care of releasing the pressed state of the button as well
|
||||
close_menus();
|
||||
menu_button_el.focus({ preventScroll: true });
|
||||
}
|
||||
e.preventDefault();
|
||||
} else {
|
||||
const window_el = menus_el.closest(".window");
|
||||
if (window_el) {
|
||||
// refocus last focused control in window
|
||||
// refocus-window should never focus the menu bar
|
||||
// it stores the last focused control in the window and specifically not in the menus
|
||||
window_el.dispatchEvent(new CustomEvent("refocus-window"));
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Alt":
|
||||
// close all menus and refocus the last focused control in the window
|
||||
close_menus();
|
||||
refocus_window();
|
||||
e.preventDefault();
|
||||
break;
|
||||
case "Space":
|
||||
// opens system menu in Windows 98
|
||||
// (at top level)
|
||||
break;
|
||||
case "Enter":
|
||||
if (menu_button_el === document.activeElement) {
|
||||
open_top_level_menu("keydown");
|
||||
e.preventDefault();
|
||||
} else {
|
||||
highlighted_item_el?.click();
|
||||
e.preventDefault();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
break;
|
||||
}
|
||||
// handle accelerators and first-letter navigation
|
||||
const key = e.key.toLowerCase();
|
||||
const item_els = active_menu_popup ?
|
||||
[...menu_popup_el.querySelectorAll(".menu-item")] :
|
||||
top_level_menus.map(top_level_menu => top_level_menu.menu_button_el);
|
||||
const item_els_by_accelerator = {};
|
||||
for (const item_el of item_els) {
|
||||
const accelerator = item_el.querySelector(".menu-hotkey");
|
||||
const accelerator_key = (accelerator ?
|
||||
accelerator.textContent :
|
||||
(item_el.querySelector(".menu-item-label") ?? item_el).textContent[0]
|
||||
).toLowerCase();
|
||||
item_els_by_accelerator[accelerator_key] = item_els_by_accelerator[accelerator_key] || [];
|
||||
item_els_by_accelerator[accelerator_key].push(item_el);
|
||||
}
|
||||
const matching_item_els = item_els_by_accelerator[key] || [];
|
||||
// console.log({ key, item_els, item_els_by_accelerator, matching_item_els });
|
||||
if (matching_item_els.length) {
|
||||
if (matching_item_els.length === 1) {
|
||||
// it's unambiguous, go ahead and activate it
|
||||
const menu_item_el = matching_item_els[0];
|
||||
// click() doesn't work for menu buttons at the moment,
|
||||
// and also we want to highlight the first item in the menu
|
||||
// in that case, which doesn't happen with the mouse
|
||||
const top_level_menu = top_level_menus.find(top_level_menu => top_level_menu.menu_button_el === menu_item_el);
|
||||
if (top_level_menu) {
|
||||
top_level_menu.open_top_level_menu("keydown");
|
||||
} else {
|
||||
menu_item_el.click();
|
||||
}
|
||||
e.preventDefault();
|
||||
} else {
|
||||
// cycle the menu items that match the key
|
||||
let index = matching_item_els.indexOf(highlighted_item_el);
|
||||
if (index === -1) {
|
||||
index = 0;
|
||||
} else {
|
||||
index = (index + 1) % matching_item_els.length;
|
||||
}
|
||||
const menu_item_el = matching_item_els[index];
|
||||
// active_menu_popup.highlight(index); // would very much not work
|
||||
active_menu_popup.highlight(menu_item_el);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
menus_el.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
// TODO: API for context menus (i.e. floating menu popups)
|
||||
function MenuPopup(menu_items, { parentMenuPopup } = {}) {
|
||||
this.parentMenuPopup = parentMenuPopup;
|
||||
this.menuItems = menu_items;
|
||||
this.itemElements = []; // one-to-one with menuItems (note: not all itemElements have class .menu-item) (@TODO: unify terminology)
|
||||
|
||||
const menu_popup_el = E("div", {
|
||||
class: "menu-popup",
|
||||
id: `menu-popup-${uid()}`,
|
||||
tabIndex: "-1",
|
||||
role: "menu",
|
||||
});
|
||||
menu_popup_el.style.touchAction = "pan-y"; // will allow for scrolling overflowing menus in the future, but prevent event delay and double tap to zoom
|
||||
menu_popup_el.style.outline = "none";
|
||||
const menu_popup_table_el = E("table", { class: "menu-popup-table", role: "presentation" });
|
||||
menu_popup_el.appendChild(menu_popup_table_el);
|
||||
|
||||
this.element = menu_popup_el;
|
||||
menu_popup_by_el.set(menu_popup_el, this);
|
||||
|
||||
let submenus = [];
|
||||
|
||||
menu_popup_el.addEventListener("keydown", handleKeyDown);
|
||||
|
||||
menu_popup_el.addEventListener("pointerleave", () => {
|
||||
// if there's a submenu popup, highlight the item for that, otherwise nothing
|
||||
|
||||
// could use aria-expanded for selecting this, alternatively
|
||||
for (const submenu of submenus) {
|
||||
if (submenu.submenu_popup_el.style.display !== "none") {
|
||||
this.highlight(submenu.item_el);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.highlight(-1);
|
||||
});
|
||||
|
||||
menu_popup_el.addEventListener("focusin", (e) => {
|
||||
// prevent focus going to menu items; as designed, it works with aria-activedescendant and focus on the menu popup itself
|
||||
// (on desktop when clicking (and dragging out) then pressing a key, or on mobile when tapping, a focus ring was visible, and it wouldn't go away with keyboard navigation either)
|
||||
menu_popup_el.focus({ preventScroll: true });
|
||||
});
|
||||
|
||||
let last_item_el;
|
||||
this.highlight = (index_or_element) => { // index includes separators
|
||||
let item_el = index_or_element;
|
||||
if (typeof index_or_element === "number") {
|
||||
item_el = this.itemElements[index_or_element];
|
||||
}
|
||||
if (last_item_el && last_item_el !== item_el) {
|
||||
last_item_el.classList.remove("highlight");
|
||||
}
|
||||
if (item_el) {
|
||||
item_el.classList.add("highlight");
|
||||
menu_popup_el.setAttribute("aria-activedescendant", item_el.id);
|
||||
last_item_el = item_el;
|
||||
} else {
|
||||
menu_popup_el.removeAttribute("aria-activedescendant");
|
||||
last_item_el = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.close = (focus_parent_menu_popup = true) => { // Note: won't focus menu bar buttons.
|
||||
// idempotent
|
||||
for (const submenu of submenus) {
|
||||
submenu.submenu_popup.close(false);
|
||||
}
|
||||
if (focus_parent_menu_popup) {
|
||||
this.parentMenuPopup?.element.focus({ preventScroll: true });
|
||||
}
|
||||
menu_popup_el.style.display = "none";
|
||||
this.highlight(-1);
|
||||
// after closing submenus, which should move the active_menu_popup to this level, move it up to the parent level
|
||||
if (active_menu_popup === this) {
|
||||
active_menu_popup = this.parentMenuPopup;
|
||||
}
|
||||
};
|
||||
|
||||
const add_menu_item = (parent_element, item, item_index) => {
|
||||
const row_el = E("tr", { class: "menu-row" });
|
||||
this.itemElements.push(row_el);
|
||||
parent_element.appendChild(row_el);
|
||||
if (item === MENU_DIVIDER) {
|
||||
const td_el = E("td", { colspan: 4 });
|
||||
const hr_el = E("hr", { class: "menu-hr" });
|
||||
// hr_el.setAttribute("role", "separator"); // this is the implicit ARIA role for <hr>
|
||||
// and setting it on the <tr> might cause problems due to multiple elements with the role
|
||||
// hopefully it's fine that the semantic <hr> is nested?
|
||||
td_el.appendChild(hr_el);
|
||||
row_el.appendChild(td_el);
|
||||
// Favorites menu behavior:
|
||||
// hr_el.addEventListener("click", () => {
|
||||
// this.highlight(-1);
|
||||
// });
|
||||
// Normal menu behavior:
|
||||
hr_el.addEventListener("pointerenter", () => {
|
||||
this.highlight(-1);
|
||||
});
|
||||
} else {
|
||||
const item_el = row_el;
|
||||
item_el.classList.add("menu-item");
|
||||
item_el.id = `menu-item-${uid()}`;
|
||||
item_el.tabIndex = -1; // may be needed for aria-activedescendant in some browsers?
|
||||
item_el.setAttribute("role", item.checkbox ? item.checkbox.type === "radio" ? "menuitemradio" : "menuitemcheckbox" : "menuitem");
|
||||
// prevent announcing the SHORTCUT (distinct from the hotkey, which would already not be announced unless it's e.g. a translated string like "새로 만들기 (&N)")
|
||||
// remove_hotkey so it doesn't announce an ampersand
|
||||
item_el.setAttribute("aria-label", remove_hotkey(item.label || item.item));
|
||||
// include the shortcut semantically; if you want to display the shortcut differently than aria-keyshortcuts syntax,
|
||||
// provide both ariaKeyShortcuts and shortcutLabel (old API: shortcut)
|
||||
item_el.setAttribute("aria-keyshortcuts", item.ariaKeyShortcuts || item.shortcut || item.shortcutLabel);
|
||||
|
||||
if (item.description) {
|
||||
item_el.setAttribute("aria-description", item.description);
|
||||
}
|
||||
const checkbox_area_el = E("td", { class: "menu-item-checkbox-area" });
|
||||
const label_el = E("td", { class: "menu-item-label" });
|
||||
const shortcut_el = E("td", { class: "menu-item-shortcut" });
|
||||
const submenu_area_el = E("td", { class: "menu-item-submenu-area" });
|
||||
|
||||
item_el.appendChild(checkbox_area_el);
|
||||
item_el.appendChild(label_el);
|
||||
item_el.appendChild(shortcut_el);
|
||||
item_el.appendChild(submenu_area_el);
|
||||
|
||||
label_el.innerHTML = display_hotkey(item.label || item.item);
|
||||
shortcut_el.textContent = item.shortcut;
|
||||
|
||||
menu_popup_el.addEventListener("update", () => {
|
||||
// item_el.disabled = is_disabled(item); // doesn't work, probably because it's a <tr>
|
||||
if (is_disabled(item)) {
|
||||
item_el.setAttribute("disabled", "");
|
||||
item_el.setAttribute("aria-disabled", "true");
|
||||
} else {
|
||||
item_el.removeAttribute("disabled");
|
||||
item_el.removeAttribute("aria-disabled");
|
||||
}
|
||||
if (item.checkbox && item.checkbox.check) {
|
||||
const checked = item.checkbox.check();
|
||||
item_el.setAttribute("aria-checked", checked ? "true" : "false");
|
||||
}
|
||||
});
|
||||
// You may ask, why not call `send_info_event` in `highlight`?
|
||||
// Consider the case where you hover to open a menu, and it sets highlight to none,
|
||||
// it shouldn't reset the status bar. It needs to be more based on the pointer and keyboard interactions directly.
|
||||
// *Maybe* it could be a parameter (to `highlight`) if that's really helpful, but it's probably not.
|
||||
// *Maybe* it could look at more of the overall state within `highlight`,
|
||||
// but could it distinguish hovering an outer vs an inner item if two are highlighted?
|
||||
item_el.addEventListener("pointerenter", () => {
|
||||
this.highlight(item_index);
|
||||
send_info_event(item);
|
||||
});
|
||||
item_el.addEventListener("pointerleave", (event) => {
|
||||
if (
|
||||
menu_popup_el.style.display !== "none" && // not "left" due to closing
|
||||
event.pointerType !== "touch" // not "left" as in finger lifting off
|
||||
) {
|
||||
send_info_event();
|
||||
}
|
||||
});
|
||||
|
||||
if (item.checkbox?.type === "radio") {
|
||||
checkbox_area_el.classList.add("radio");
|
||||
} else if (item.checkbox) {
|
||||
checkbox_area_el.classList.add("checkbox");
|
||||
}
|
||||
|
||||
let open_submenu, submenu_popup_el;
|
||||
if (item.submenu) {
|
||||
item_el.classList.add("has-submenu"); // @TODO: remove this, and use [aria-haspopup] instead (note true = menu)
|
||||
submenu_area_el.classList.toggle("point-right", get_direction() === "rtl");
|
||||
|
||||
const submenu_popup = new MenuPopup(item.submenu, { parentMenuPopup: this });
|
||||
submenu_popup_el = submenu_popup.element;
|
||||
document.body?.appendChild(submenu_popup_el);
|
||||
submenu_popup_el.style.display = "none";
|
||||
|
||||
item_el.setAttribute("aria-haspopup", "true");
|
||||
item_el.setAttribute("aria-expanded", "false");
|
||||
item_el.setAttribute("aria-controls", submenu_popup_el.id);
|
||||
|
||||
submenu_popup_by_menu_item_el.set(item_el, submenu_popup);
|
||||
parent_item_el_by_popup_el.set(submenu_popup_el, item_el);
|
||||
submenu_popup_el.dataset.semanticParent = menu_popup_el.id; // for $Window to understand the popup belongs to its window
|
||||
menu_popup_el.setAttribute("aria-owns", `${menu_popup_el.getAttribute("aria-owns") || ""} ${submenu_popup_el.id}`);
|
||||
submenu_popup_el.setAttribute("aria-labelledby", item_el.id);
|
||||
|
||||
|
||||
open_submenu = (highlight_first = true) => {
|
||||
if (submenu_popup_el.style.display !== "none") {
|
||||
return;
|
||||
}
|
||||
if (item_el.getAttribute("aria-disabled") === "true") {
|
||||
return;
|
||||
}
|
||||
close_submenus_at_this_level();
|
||||
|
||||
item_el.setAttribute("aria-expanded", "true");
|
||||
|
||||
submenu_popup_el.style.display = "";
|
||||
submenu_popup_el.style.zIndex = get_new_menu_z_index();
|
||||
submenu_popup_el.setAttribute("dir", get_direction());
|
||||
if (window.inheritTheme) {
|
||||
window.inheritTheme(submenu_popup_el, menu_popup_el);
|
||||
}
|
||||
if (!submenu_popup_el.parentElement) {
|
||||
document.body.appendChild(submenu_popup_el);
|
||||
}
|
||||
|
||||
// console.log("open_submenu — submenu_popup_el.style.zIndex", submenu_popup_el.style.zIndex, "$Window.Z_INDEX", $Window.Z_INDEX, "menus_el.closest('.window').style.zIndex", menus_el.closest(".window").style.zIndex);
|
||||
// setTimeout(() => { console.log("after timeout, menus_el.closest('.window').style.zIndex", menus_el.closest(".window").style.zIndex); }, 0);
|
||||
submenu_popup_el.dispatchEvent(new CustomEvent("update"), {});
|
||||
if (highlight_first) {
|
||||
submenu_popup.highlight(0);
|
||||
send_info_event(submenu_popup.menuItems[0]);
|
||||
} else {
|
||||
submenu_popup.highlight(-1);
|
||||
// send_info_event(); // no, keep the status bar text!
|
||||
}
|
||||
|
||||
const rect = item_el.getBoundingClientRect();
|
||||
let submenu_popup_rect = submenu_popup_el.getBoundingClientRect();
|
||||
submenu_popup_el.style.position = "absolute";
|
||||
submenu_popup_el.style.left = `${(get_direction() === "rtl" ? rect.left - submenu_popup_rect.width : rect.right) + window.scrollX}px`;
|
||||
submenu_popup_el.style.top = `${rect.top + window.scrollY}px`;
|
||||
|
||||
submenu_popup_rect = submenu_popup_el.getBoundingClientRect();
|
||||
// This is surely not the cleanest way of doing this,
|
||||
// and the logic is not very robust in the first place,
|
||||
// but I want to get RTL support done and so I'm mirroring this in the simplest way possible.
|
||||
if (get_direction() === "rtl") {
|
||||
if (submenu_popup_rect.left < 0) {
|
||||
submenu_popup_el.style.left = `${rect.right}px`;
|
||||
submenu_popup_rect = submenu_popup_el.getBoundingClientRect();
|
||||
if (submenu_popup_rect.right > innerWidth) {
|
||||
submenu_popup_el.style.left = `${innerWidth - submenu_popup_rect.width}px`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (submenu_popup_rect.right > innerWidth) {
|
||||
submenu_popup_el.style.left = `${rect.left - submenu_popup_rect.width}px`;
|
||||
submenu_popup_rect = submenu_popup_el.getBoundingClientRect();
|
||||
if (submenu_popup_rect.left < 0) {
|
||||
submenu_popup_el.style.left = "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
submenu_popup_el.focus({ preventScroll: true });
|
||||
active_menu_popup = submenu_popup;
|
||||
};
|
||||
|
||||
submenus.push({
|
||||
item_el,
|
||||
submenu_popup_el,
|
||||
submenu_popup,
|
||||
});
|
||||
|
||||
function close_submenus_at_this_level() {
|
||||
for (const { submenu_popup, item_el } of submenus) {
|
||||
submenu_popup.close(false);
|
||||
item_el.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
menu_popup_el.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
// It should close when hovering a different higher level menu
|
||||
// after a delay, unless the mouse returns to the submenu.
|
||||
// If you return the mouse from a submenu into its parent
|
||||
// *directly onto the parent menu item*, it stays open, but if you cross other menu items
|
||||
// in the parent menu, (@TODO:) it'll close after the delay even if you land on the parent menu item.
|
||||
// Once a submenu opens (completing its animation if it has one),
|
||||
// - up/down should navigate the submenu (although it should not show as focused right away)
|
||||
// (i.e. up/down always navigate the most-nested open submenu, as long as it's not animating, in which case nothing happens)
|
||||
// - @TODO: the submenu cancels its closing timeout (if you've moved outside all menus, say)
|
||||
// (but if you move outside menus AFTER the submenu has opened, it should start the closing timeout)
|
||||
// @TODO: make this more robust in general! Make some automated tests.
|
||||
|
||||
let open_tid, close_tid;
|
||||
submenu_popup_el.addEventListener("pointerenter", () => {
|
||||
if (open_tid) { clearTimeout(open_tid); open_tid = null; }
|
||||
if (close_tid) { clearTimeout(close_tid); close_tid = null; }
|
||||
});
|
||||
item_el.addEventListener("pointerenter", () => {
|
||||
// @TODO: don't cancel close timer? in Windows 98 it'll still close after a delay if you hover the submenu's parent item
|
||||
if (open_tid) { clearTimeout(open_tid); open_tid = null; }
|
||||
if (close_tid) { clearTimeout(close_tid); close_tid = null; }
|
||||
open_tid = setTimeout(() => {
|
||||
open_submenu(false);
|
||||
}, 501); // @HACK: slightly longer than close timer so it doesn't close immediately
|
||||
});
|
||||
item_el.addEventListener("pointerleave", () => {
|
||||
if (open_tid) { clearTimeout(open_tid); open_tid = null; }
|
||||
});
|
||||
menu_popup_el.addEventListener("pointerenter", (event) => {
|
||||
// console.log(event.target.closest(".menu-item"));
|
||||
if (event.target.closest(".menu-item") === item_el) {
|
||||
return;
|
||||
}
|
||||
if (!close_tid) {
|
||||
// This is a little confusing, with timers per-item...
|
||||
// @TODO: try doing this with just one or two timers.
|
||||
// if (submenus.some(submenu => submenu.submenu_popup_el.style.display !== "none")) {
|
||||
if (submenu_popup_el.style.display !== "none") {
|
||||
close_tid = setTimeout(() => {
|
||||
if (!window.debugKeepMenusOpen) {
|
||||
// close_submenu();
|
||||
close_submenus_at_this_level();
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
});
|
||||
// keep submenu open while mouse is outside any parent menus
|
||||
// (@TODO: what if it goes to another parent menu though?)
|
||||
menu_popup_el.addEventListener("pointerleave", () => {
|
||||
if (close_tid) { clearTimeout(close_tid); close_tid = null; }
|
||||
});
|
||||
|
||||
item_el.addEventListener("pointerdown", () => { open_submenu(false); });
|
||||
}
|
||||
|
||||
let just_activated = false; // to prevent double-activation from pointerup + click
|
||||
const item_action = () => {
|
||||
if (just_activated) {
|
||||
return;
|
||||
}
|
||||
just_activated = true;
|
||||
setTimeout(() => { just_activated = false; }, 10);
|
||||
|
||||
if (item.checkbox) {
|
||||
if (item.checkbox.toggle) {
|
||||
item.checkbox.toggle();
|
||||
}
|
||||
menu_popup_el.dispatchEvent(new CustomEvent("update"), {});
|
||||
} else if (item.action) {
|
||||
close_menus();
|
||||
refocus_window(); // before action, so things like copy/paste have a better chance of working
|
||||
item.action();
|
||||
}
|
||||
};
|
||||
// pointerup is for gliding to menu items to activate
|
||||
item_el.addEventListener("pointerup", e => {
|
||||
if (e.pointerType === "mouse" && e.button !== 0) {
|
||||
return;
|
||||
}
|
||||
if (e.pointerType === "touch") {
|
||||
// Will use click instead; otherwise focus is lost on a delay: if it opens a dialog for example,
|
||||
// you have to hold down on the menu item for a bit otherwise it'll blur the dialog after opening.
|
||||
// I think this is caused by the pointer falling through to elements without touch-action defined.
|
||||
// RIGHT NOW, gliding to menu items isn't supported for touch anyways,
|
||||
// although I'd like to support it in the future.
|
||||
// Well, it might have accessibility problems, so maybe not. I think this is fine.
|
||||
return;
|
||||
}
|
||||
item_el.click();
|
||||
});
|
||||
item_el.addEventListener("click", e => {
|
||||
if (item.submenu) {
|
||||
open_submenu(true);
|
||||
} else {
|
||||
item_action();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (menu_items.length === 0) {
|
||||
menu_items = [{
|
||||
label: "(Empty)",
|
||||
enabled: false,
|
||||
}];
|
||||
}
|
||||
let init_index = 0;
|
||||
for (const item of menu_items) {
|
||||
if (item.radioItems) {
|
||||
const tbody = E("tbody", { role: "group" }); // multiple tbody elements are allowed, can be used for grouping rows,
|
||||
// and in this case providing an ARIA role for the radio group.
|
||||
if (item.ariaLabel) {
|
||||
tbody.setAttribute("aria-label", item.ariaLabel);
|
||||
}
|
||||
|
||||
for (const radio_item of item.radioItems) {
|
||||
radio_item.checkbox = {
|
||||
type: "radio",
|
||||
check: () => radio_item.value === item.getValue(),
|
||||
toggle: () => {
|
||||
item.setValue(radio_item.value);
|
||||
},
|
||||
};
|
||||
add_menu_item(tbody, radio_item, init_index++);
|
||||
}
|
||||
menu_popup_table_el.appendChild(tbody);
|
||||
} else {
|
||||
add_menu_item(menu_popup_table_el, item, init_index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// let this_click_opened_the_menu = false;
|
||||
const make_menu_button = (menus_key, menu_items) => {
|
||||
const menu_button_el = E("div", {
|
||||
class: "menu-button",
|
||||
"aria-expanded": "false",
|
||||
"aria-haspopup": "true",
|
||||
role: "menuitem",
|
||||
});
|
||||
|
||||
menus_el.appendChild(menu_button_el);
|
||||
|
||||
const menu_popup = new MenuPopup(menu_items);
|
||||
const menu_popup_el = menu_popup.element;
|
||||
document.body?.appendChild(menu_popup_el);
|
||||
submenu_popup_by_menu_item_el.set(menu_button_el, menu_popup);
|
||||
parent_item_el_by_popup_el.set(menu_popup_el, menu_button_el);
|
||||
menu_button_el.id = `menu-button-${menus_key}-${uid()}`;
|
||||
menu_popup_el.dataset.semanticParent = menu_button_el.id; // for $Window to understand the popup belongs to its window
|
||||
menu_button_el.setAttribute("aria-controls", menu_popup_el.id);
|
||||
menu_popup_el.setAttribute("aria-labelledby", menu_button_el.id);
|
||||
menus_el.setAttribute("aria-owns", `${menus_el.getAttribute("aria-owns") || ""} ${menu_popup_el.id}`);
|
||||
|
||||
const update_position_from_containing_bounds = () => {
|
||||
const rect = menu_button_el.getBoundingClientRect();
|
||||
let popup_rect = menu_popup_el.getBoundingClientRect();
|
||||
menu_popup_el.style.position = "absolute";
|
||||
menu_popup_el.style.left = `${(get_direction() === "rtl" ? rect.right - popup_rect.width : rect.left) + window.scrollX}px`;
|
||||
menu_popup_el.style.top = `${rect.bottom + window.scrollY}px`;
|
||||
|
||||
const uncorrected_rect = menu_popup_el.getBoundingClientRect();
|
||||
// rounding down is needed for RTL layout for the rightmost menu, to prevent a scrollbar
|
||||
if (Math.floor(uncorrected_rect.right) > innerWidth) {
|
||||
menu_popup_el.style.left = `${innerWidth - uncorrected_rect.width}px`;
|
||||
}
|
||||
if (Math.ceil(uncorrected_rect.left) < 0) {
|
||||
menu_popup_el.style.left = "0px";
|
||||
}
|
||||
};
|
||||
window.addEventListener("resize", update_position_from_containing_bounds);
|
||||
menu_popup_el.addEventListener("update", update_position_from_containing_bounds);
|
||||
// update_position_from_containing_bounds(); // will be called when the menu is opened
|
||||
|
||||
const menu_id = menus_key.replace("&", "").replace(/ /g, "-").toLowerCase();
|
||||
menu_button_el.classList.add(`${menu_id}-menu-button`);
|
||||
// menu_popup_el.id = `${menu_id}-menu-popup-${uid()}`; // id is created by MenuPopup and changing it breaks the data-semantic-parent relationship
|
||||
menu_popup_el.style.display = "none";
|
||||
menu_button_el.innerHTML = display_hotkey(menus_key);
|
||||
menu_button_el.tabIndex = -1;
|
||||
|
||||
menu_button_el.setAttribute("aria-haspopup", "true");
|
||||
menu_button_el.setAttribute("aria-controls", menu_popup_el.id);
|
||||
|
||||
menu_button_el.addEventListener("focus", () => {
|
||||
top_level_highlight(menus_key);
|
||||
});
|
||||
menu_button_el.addEventListener("pointerdown", e => {
|
||||
if (menu_button_el.classList.contains("active")) {
|
||||
menu_button_el.dispatchEvent(new CustomEvent("release", {}));
|
||||
refocus_window();
|
||||
e.preventDefault(); // needed for refocus_window() to work
|
||||
} else {
|
||||
open_top_level_menu(e.type);
|
||||
}
|
||||
});
|
||||
menu_button_el.addEventListener("pointermove", e => {
|
||||
top_level_highlight(menus_key);
|
||||
if (e.pointerType === "touch") {
|
||||
return;
|
||||
}
|
||||
if (selecting_menus) {
|
||||
open_top_level_menu(e.type);
|
||||
}
|
||||
});
|
||||
function open_top_level_menu(type = "other") {
|
||||
|
||||
const new_index = Object.keys(menus).indexOf(menus_key);
|
||||
if (new_index === top_level_menu_index && menu_button_el.getAttribute("aria-expanded") === "true") {
|
||||
return; // already open
|
||||
}
|
||||
|
||||
close_menus();
|
||||
|
||||
menu_button_el.classList.add("active");
|
||||
menu_button_el.setAttribute("aria-expanded", "true");
|
||||
menu_popup_el.style.display = "";
|
||||
menu_popup_el.style.zIndex = get_new_menu_z_index();
|
||||
menu_popup_el.setAttribute("dir", get_direction());
|
||||
if (window.inheritTheme) {
|
||||
window.inheritTheme(menu_popup_el, menus_el);
|
||||
}
|
||||
if (!menu_popup_el.parentElement) {
|
||||
document.body.appendChild(menu_popup_el);
|
||||
}
|
||||
// console.log("pointerdown (possibly simulated) — menu_popup_el.style.zIndex", menu_popup_el.style.zIndex, "$Window.Z_INDEX", $Window.Z_INDEX, "menus_el.closest('.window').style.zIndex", menus_el.closest(".window").style.zIndex);
|
||||
// setTimeout(() => { console.log("after timeout, menus_el.closest('.window').style.zIndex", menus_el.closest(".window").style.zIndex); }, 0);
|
||||
top_level_highlight(menus_key);
|
||||
|
||||
menu_popup_el.dispatchEvent(new CustomEvent("update"), {});
|
||||
|
||||
selecting_menus = true;
|
||||
|
||||
menu_popup_el.focus({ preventScroll: true });
|
||||
active_menu_popup = menu_popup;
|
||||
|
||||
if (type === "keydown") {
|
||||
menu_popup.highlight(0);
|
||||
send_info_event(menu_popup.menuItems[0]);
|
||||
} else {
|
||||
send_info_event(); // @TODO: allow descriptions on top level menus
|
||||
}
|
||||
};
|
||||
menu_button_el.addEventListener("release", () => {
|
||||
selecting_menus = false;
|
||||
|
||||
menu_button_el.classList.remove("active");
|
||||
if (!window.debugKeepMenusOpen) {
|
||||
menu_popup.close(true);
|
||||
menu_button_el.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
|
||||
menus_el.dispatchEvent(new CustomEvent("default-info", {}));
|
||||
});
|
||||
top_level_menus.push({
|
||||
menu_button_el,
|
||||
menu_popup_el,
|
||||
menus_key,
|
||||
hotkey: get_hotkey(menus_key),
|
||||
open_top_level_menu,
|
||||
});
|
||||
};
|
||||
for (const menu_key in menus) {
|
||||
make_menu_button(menu_key, menus[menu_key]);
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", e => {
|
||||
// close any errant menus
|
||||
// taking care not to interfere with regular Escape key behavior
|
||||
// @TODO: listen for menus_el removed from DOM, and close menus there
|
||||
if (
|
||||
!document.activeElement ||
|
||||
!document.activeElement.closest || // window or document
|
||||
!document.activeElement.closest(".menus, .menu-popup")
|
||||
) {
|
||||
if (e.key === "Escape") {
|
||||
if (active_menu_popup) {
|
||||
close_menus();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// window.addEventListener("blur", close_menus);
|
||||
window.addEventListener("blur", (event) => {
|
||||
// hack for Pinball (in 98.js.org) where it triggers fake blur events
|
||||
// in order to pause the game
|
||||
if (!event.isTrusted) {
|
||||
return;
|
||||
}
|
||||
close_menus();
|
||||
});
|
||||
function close_menus_on_click_outside(event) {
|
||||
if (event.target?.closest?.(".menus") === menus_el || event.target?.closest?.(".menu-popup")) {
|
||||
return;
|
||||
}
|
||||
// window.console && console.log(event.type, "occurred outside of menus (on ", event.target, ") so...");
|
||||
close_menus();
|
||||
top_level_highlight(-1);
|
||||
}
|
||||
window.addEventListener("pointerdown", close_menus_on_click_outside);
|
||||
window.addEventListener("pointerup", close_menus_on_click_outside);
|
||||
|
||||
window.addEventListener("focusout", (event) => {
|
||||
// if not still in menus, unhighlight (e.g. if you hit Escape to unfocus the menus)
|
||||
if (event.relatedTarget?.closest?.(".menus") === menus_el || event.relatedTarget?.closest?.(".menu-popup")) {
|
||||
return;
|
||||
}
|
||||
close_menus();
|
||||
// Top level buttons should no longer be highlighted due to focus, but still may be highlighted due to hover.
|
||||
top_level_highlight(top_level_menus.findIndex(({ menu_button_el }) => menu_button_el.matches(":hover")));
|
||||
});
|
||||
|
||||
let keyboard_scope_elements = [];
|
||||
function set_keyboard_scope(...elements) {
|
||||
for (const el of keyboard_scope_elements) {
|
||||
el.removeEventListener("keydown", keyboard_scope_keydown);
|
||||
}
|
||||
keyboard_scope_elements = elements;
|
||||
for (const el of keyboard_scope_elements) {
|
||||
el.addEventListener("keydown", keyboard_scope_keydown);
|
||||
}
|
||||
}
|
||||
function keyboard_scope_keydown(e) {
|
||||
// Close menus if the user presses almost any key combination
|
||||
// e.g. if you look in the menu to remember a shortcut,
|
||||
// and then use the shortcut.
|
||||
if (
|
||||
(e.ctrlKey || e.metaKey) && // Ctrl or Command held down
|
||||
// and anything then pressed other than Ctrl or Command
|
||||
e.key !== "Control" &&
|
||||
e.key !== "Meta"
|
||||
) {
|
||||
close_menus();
|
||||
return;
|
||||
}
|
||||
if (e.defaultPrevented) {
|
||||
return; // closing menus above is meant to be done when activating unrelated shortcuts
|
||||
// but stuff after this is should not be handled at the same time as something else
|
||||
}
|
||||
if (e.altKey && !e.shiftKey && !e.ctrlKey && !e.metaKey) { // Alt held
|
||||
const menu = top_level_menus.find((menu) =>
|
||||
menu.hotkey.toLowerCase() === e.key.toLowerCase()
|
||||
);
|
||||
if (menu) {
|
||||
e.preventDefault();
|
||||
menu.open_top_level_menu("keydown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_keyboard_scope(window);
|
||||
|
||||
this.element = menus_el;
|
||||
this.closeMenus = close_menus;
|
||||
this.setKeyboardScope = set_keyboard_scope;
|
||||
}
|
||||
|
||||
exports.MenuBar = MenuBar;
|
||||
exports.MENU_DIVIDER = MENU_DIVIDER;
|
||||
|
||||
})(window);
|
||||
49
static/html/jspaint/lib/os-gui/blue.css
Normal file
49
static/html/jspaint/lib/os-gui/blue.css
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Source: https://www.deviantart.com/tpenguinltg/art/Blue-525167751 */
|
||||
/* License: https://creativecommons.org/licenses/by-sa/3.0/ */
|
||||
/* This is a generated file. */
|
||||
:root {
|
||||
--checker: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2O8/OTH/8vPfjAwLjv14b+uFAcDAG90ChC/AKc5AAAAAElFTkSuQmCC");
|
||||
--button-active-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22rgb(49%2C%20131%2C%20221)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22rgb(166%2C%20202%2C%20240)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--button-normal-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22rgb(211%2C%20228%2C%20248)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22rgb(166%2C%20202%2C%20240)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22rgb(49%2C%20131%2C%20221)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22rgb(166%2C%20202%2C%20240)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--inset-deep-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22rgb(211%2C%20228%2C%20248)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22rgb(49%2C%20131%2C%20221)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22rgb(166%2C%20202%2C%20240)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22rgb(166%2C%20202%2C%20240)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--button-default-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22rgb(211%2C%20228%2C%20248)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h96v32h-64v64h-32v-96z%22%20fill%3D%22rgb(166%2C%20202%2C%20240)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M160%2064h32v128h-128v-32h96v-96z%22%20fill%3D%22rgb(49%2C%20131%2C%20221)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M96%2096h64v64h-64v-64z%22%20fill%3D%22rgb(166%2C%20202%2C%20240)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 96 / 3px;
|
||||
--button-default-active-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22rgb(49%2C%20131%2C%20221)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22rgb(166%2C%20202%2C%20240)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--scrollbar-arrows-ButtonText: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAW0lEQVQ4T2NkGGSAcZC5h4FWDvrPwEC02ShqkR0EkkAHuBxMyEKYWYQ8jKEOXQOyo/A5BuZwqqvBZiA+3xMbilQLIWqlcUJRimwPzjRELcdQZA6hREeR4eRoBgBoXhAK6oiMhwAAAABJRU5ErkJggg==");
|
||||
--scrollbar-arrows-GrayText: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDjJsvvv/fK0yUWajq4VrAkmghxYuQwlZCDOLkKOwqUPxBbKj8DkG5nBaqMEIVny+JzYUqRZC1ErghKIU2R6caYhajqHUHKJyAqWWkKIfANj2QArAsbtdAAAAAElFTkSuQmCC");
|
||||
--scrollbar-arrows-ButtonHilight: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDrr85Md/XRkOosxGVwvXBJJADy1chhKyEGYWIUdhU4fiC2RH4XMMzOG0UIMRrPh8T2woUi2EqJXACUUpsj040xC1HEOpOUTlBEotIUU/AHnlQApCJ0jDAAAAAElFTkSuQmCC");
|
||||
--scrollbar-size: 13px;
|
||||
--scrollbar-button-inner-size: 9px;
|
||||
--ActiveTitle: rgb(0, 0, 128);
|
||||
--Background: rgb(58, 110, 165);
|
||||
--Hilight: rgb(51, 153, 255);
|
||||
--HilightText: rgb(255, 255, 255);
|
||||
--TitleText: rgb(255, 255, 255);
|
||||
--Window: rgb(255, 255, 255);
|
||||
--WindowText: rgb(0, 0, 0);
|
||||
--Scrollbar: rgb(211, 228, 248);
|
||||
--InactiveTitle: rgb(49, 131, 221);
|
||||
--Menu: rgb(166, 202, 240);
|
||||
--WindowFrame: rgb(0, 0, 0);
|
||||
--MenuText: rgb(0, 0, 0);
|
||||
--ActiveBorder: rgb(166, 202, 240);
|
||||
--InactiveBorder: rgb(166, 202, 240);
|
||||
--AppWorkspace: rgb(49, 131, 221);
|
||||
--ButtonFace: rgb(166, 202, 240);
|
||||
--ButtonShadow: rgb(49, 131, 221);
|
||||
--GrayText: rgb(49, 131, 221);
|
||||
--ButtonText: rgb(0, 0, 0);
|
||||
--InactiveTitleText: rgb(0, 0, 128);
|
||||
--ButtonHilight: rgb(211, 228, 248);
|
||||
--ButtonDkShadow: rgb(0, 0, 0);
|
||||
--ButtonLight: rgb(166, 202, 240);
|
||||
--InfoText: rgb(0, 0, 0);
|
||||
--InfoWindow: rgb(225, 225, 255);
|
||||
--GradientActiveTitle: rgb(16, 132, 208);
|
||||
--GradientInactiveTitle: rgb(49, 131, 221);
|
||||
--ButtonAlternateFace: rgb(192, 192, 192);
|
||||
--HotTrackingColor: rgb(0, 0, 128);
|
||||
--MenuHilight: rgb(0, 0, 128);
|
||||
--MenuBar: rgb(166, 202, 240);
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=blue.css.map */
|
||||
1
static/html/jspaint/lib/os-gui/blue.css.map
Normal file
1
static/html/jspaint/lib/os-gui/blue.css.map
Normal file
File diff suppressed because one or more lines are too long
108
static/html/jspaint/lib/os-gui/layout.css
Normal file
108
static/html/jspaint/lib/os-gui/layout.css
Normal file
@@ -0,0 +1,108 @@
|
||||
.menus,
|
||||
.menu-popup,
|
||||
.os-window,
|
||||
.os-window .window-titlebar,
|
||||
.os-window .window-title {
|
||||
cursor: default;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.os-window {
|
||||
contain: layout; /* contain: paint; seems to clip children to the padding-box, including for interaction, not just painting; it breaks being able to grab resize handles over the border */
|
||||
/* overflow: hidden; is also not usable for the same reason */
|
||||
/* I might be able to do either with overflow-clip-margin however (@TODO) */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* will-change: width height left top; */
|
||||
}
|
||||
.window-content {
|
||||
flex: 1;
|
||||
min-height: 0px;
|
||||
/* Text overflowing the window frame is really ugly!
|
||||
overflow: hidden; would make it harder to enable scrollbars (overflow: auto !important)
|
||||
We want to allow scrollbars to be enabled easily (but not enable them),
|
||||
and we want to clip to the border of the window, without contents overlapping the border at all. */
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
.os-window .window-titlebar,
|
||||
body > .window-titlebar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.os-window .window-title-area {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.os-window .window-titlebar .icon {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.os-window.maximized .handle,
|
||||
.os-window.minimized-without-taskbar .handle {
|
||||
display: none; /* prevent resizing when window is minimized */
|
||||
}
|
||||
|
||||
/* Fix dragging things (like windows) over iframes */
|
||||
.dragging iframe {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.menus {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.menu-popup {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.menu-popup-table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.menu-button,
|
||||
.menu-item {
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
/* text-overflow: ellipsis; might imply a dialog */
|
||||
}
|
||||
.menu-hr {
|
||||
display: block !important;
|
||||
height: 0;
|
||||
width: auto;
|
||||
}
|
||||
.menu-hotkey {
|
||||
display: inline !important;
|
||||
}
|
||||
.menu-item-checkbox-area,
|
||||
.menu-item-submenu-area {
|
||||
min-width: 16px;
|
||||
}
|
||||
.menu-item-checkbox-area,
|
||||
.menu-item-submenu-area {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* .window-content .button-group {
|
||||
width: 85px;
|
||||
}
|
||||
.window-content .button-group > button {
|
||||
width: 95%;
|
||||
padding: 3px 5px;
|
||||
} */
|
||||
|
||||
::before,
|
||||
::after {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=layout.css.map */
|
||||
1
static/html/jspaint/lib/os-gui/layout.css.map
Normal file
1
static/html/jspaint/lib/os-gui/layout.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../src/layout.css"],"names":[],"mappings":"AAAA;;;;;CAKC,eAAe;CACf,yBAAiB;IAAjB,sBAAiB;KAAjB,qBAAiB;SAAjB,iBAAiB;AAClB;;AAEA;CACC,eAAe,EAAE,yKAAyK;CAC1L,6DAA6D;CAC7D,2EAA2E;CAC3E,aAAa;CACb,sBAAsB;CACtB,wCAAwC;AACzC;AACA;CACC,OAAO;CACP,eAAe;CACf;;;mGAGkG;IAC/F,qBAAqB;AACzB;;AAEA;;CAEC,aAAa;CACb,mBAAmB;CACnB,mBAAmB;CACnB,mBAAmB;CACnB,gBAAgB;CAChB,cAAc;AACf;AACA;CACC,kBAAkB;CAClB,OAAO;AACR;;AAEA;CACC,sBAAsB;AACvB;;AAEA;;CAEC,aAAa,EAAE,8CAA8C;AAC9D;;AAEA,oDAAoD;AACpD;CACC,oBAAoB;AACrB;;AAEA;CACC,aAAa;CACb,cAAc;CACd,eAAe;AAChB;AACA;CACC,kBAAkB;CAClB,sBAAsB;AACvB;AACA;CACC,yBAAyB;AAC1B;AACA;;CAEC,mBAAmB;IAChB,eAAe;IACf,gBAAgB;IAChB,kDAAkD;AACtD;AACA;CACC,yBAAyB;CACzB,SAAS;CACT,WAAW;AACZ;AACA;CACC,0BAA0B;AAC3B;AACA;;CAEC,eAAe;AAChB;AACA;;CAEC,kBAAkB;AACnB;;AAEA;;;;;;GAMG;;AAEH;;CAEC,oBAAoB;AACrB","file":"layout.css","sourcesContent":[".menus,\n.menu-popup,\n.os-window,\n.os-window .window-titlebar,\n.os-window .window-title {\n\tcursor: default;\n\tuser-select: none;\n}\n\n.os-window {\n\tcontain: layout; /* contain: paint; seems to clip children to the padding-box, including for interaction, not just painting; it breaks being able to grab resize handles over the border */\n\t/* overflow: hidden; is also not usable for the same reason */\n\t/* I might be able to do either with overflow-clip-margin however (@TODO) */\n\tdisplay: flex;\n\tflex-direction: column;\n\t/* will-change: width height left top; */\n}\n.window-content {\n\tflex: 1;\n\tmin-height: 0px;\n\t/* Text overflowing the window frame is really ugly!\n\toverflow: hidden; would make it harder to enable scrollbars (overflow: auto !important)\n\tWe want to allow scrollbars to be enabled easily (but not enable them),\n\tand we want to clip to the border of the window, without contents overlapping the border at all. */\n contain: layout paint;\n}\n\n.os-window .window-titlebar,\nbody > .window-titlebar {\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\tflex-shrink: 0;\n}\n.os-window .window-title-area {\n\tposition: relative;\n\tflex: 1;\n}\n\n.os-window .window-titlebar .icon {\n\tvertical-align: bottom;\n}\n\n.os-window.maximized .handle,\n.os-window.minimized-without-taskbar .handle {\n\tdisplay: none; /* prevent resizing when window is minimized */\n}\n\n/* Fix dragging things (like windows) over iframes */\n.dragging iframe {\n\tpointer-events: none;\n}\n\n.menus {\n\tdisplay: flex;\n\tflex: 0 0 auto;\n\tflex-wrap: wrap;\n}\n.menu-popup {\n\tposition: absolute;\n\tbox-sizing: border-box;\n}\n.menu-popup-table {\n\tborder-collapse: collapse;\n}\n.menu-button,\n.menu-item {\n\twhite-space: nowrap;\n max-width: 100%;\n overflow: hidden;\n /* text-overflow: ellipsis; might imply a dialog */\n}\n.menu-hr {\n\tdisplay: block !important;\n\theight: 0;\n\twidth: auto;\n}\n.menu-hotkey {\n\tdisplay: inline !important;\n}\n.menu-item-checkbox-area,\n.menu-item-submenu-area {\n\tmin-width: 16px;\n}\n.menu-item-checkbox-area,\n.menu-item-submenu-area {\n\ttext-align: center;\n}\n\n/* .window-content .button-group {\n\twidth: 85px;\n}\n.window-content .button-group > button {\n\twidth: 95%;\n\tpadding: 3px 5px;\n} */\n\n::before,\n::after {\n\tpointer-events: none;\n}\n"]}
|
||||
106
static/html/jspaint/lib/os-gui/layout.rtl.css
Normal file
106
static/html/jspaint/lib/os-gui/layout.rtl.css
Normal file
@@ -0,0 +1,106 @@
|
||||
.menus,
|
||||
.menu-popup,
|
||||
.os-window,
|
||||
.os-window .window-titlebar,
|
||||
.os-window .window-title {
|
||||
cursor: default;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.os-window {
|
||||
contain: layout; /* contain: paint; seems to clip children to the padding-box, including for interaction, not just painting; it breaks being able to grab resize handles over the border */
|
||||
/* overflow: hidden; is also not usable for the same reason */
|
||||
/* I might be able to do either with overflow-clip-margin however (@TODO) */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* will-change: width height left top; */
|
||||
}
|
||||
.window-content {
|
||||
flex: 1;
|
||||
min-height: 0px;
|
||||
/* Text overflowing the window frame is really ugly!
|
||||
overflow: hidden; would make it harder to enable scrollbars (overflow: auto !important)
|
||||
We want to allow scrollbars to be enabled easily (but not enable them),
|
||||
and we want to clip to the border of the window, without contents overlapping the border at all. */
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
.os-window .window-titlebar,
|
||||
body > .window-titlebar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.os-window .window-title-area {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.os-window .window-titlebar .icon {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.os-window.maximized .handle,
|
||||
.os-window.minimized-without-taskbar .handle {
|
||||
display: none; /* prevent resizing when window is minimized */
|
||||
}
|
||||
|
||||
/* Fix dragging things (like windows) over iframes */
|
||||
.dragging iframe {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.menus {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.menu-popup {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.menu-popup-table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.menu-button,
|
||||
.menu-item {
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
/* text-overflow: ellipsis; might imply a dialog */
|
||||
}
|
||||
.menu-hr {
|
||||
display: block !important;
|
||||
height: 0;
|
||||
width: auto;
|
||||
}
|
||||
.menu-hotkey {
|
||||
display: inline !important;
|
||||
}
|
||||
.menu-item-checkbox-area,
|
||||
.menu-item-submenu-area {
|
||||
min-width: 16px;
|
||||
}
|
||||
.menu-item-checkbox-area,
|
||||
.menu-item-submenu-area {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* .window-content .button-group {
|
||||
width: 85px;
|
||||
}
|
||||
.window-content .button-group > button {
|
||||
width: 95%;
|
||||
padding: 3px 5px;
|
||||
} */
|
||||
|
||||
::before,
|
||||
::after {
|
||||
pointer-events: none;
|
||||
}
|
||||
372
static/html/jspaint/lib/os-gui/parse-theme.js
Normal file
372
static/html/jspaint/lib/os-gui/parse-theme.js
Normal file
@@ -0,0 +1,372 @@
|
||||
function parseINIString(data) {
|
||||
var regex = {
|
||||
section: /^\s*\[\s*([^\]]*)\s*\]\s*$/,
|
||||
param: /^\s*([^=]+?)\s*=\s*(.*?)\s*$/,
|
||||
comment: /^\s*;.*$/
|
||||
};
|
||||
var value = {};
|
||||
var lines = data.split(/[\r\n]+/);
|
||||
var section = null;
|
||||
lines.forEach(function (line) {
|
||||
if (regex.comment.test(line)) {
|
||||
return;
|
||||
} else if (regex.param.test(line)) {
|
||||
var match = line.match(regex.param);
|
||||
if (section) {
|
||||
value[section][match[1]] = match[2];
|
||||
} else {
|
||||
value[match[1]] = match[2];
|
||||
}
|
||||
} else if (regex.section.test(line)) {
|
||||
var match = line.match(regex.section);
|
||||
value[match[1]] = {};
|
||||
section = match[1];
|
||||
} else if (line.length == 0 && section) {
|
||||
section = null;
|
||||
};
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
// takes a CSSStyleDeclaration or simple object of CSS properties
|
||||
function renderThemeGraphics(cssProperties) {
|
||||
var getProp = (propName) => cssProperties.getPropertyValue ? cssProperties.getPropertyValue(propName) : cssProperties[propName];
|
||||
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = canvas.height = 2;
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = getProp("--ButtonFace");
|
||||
ctx.fillRect(0, 1, 1, 1);
|
||||
ctx.fillRect(1, 0, 1, 1);
|
||||
ctx.fillStyle = getProp("--ButtonHilight");
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
ctx.fillRect(1, 1, 1, 1);
|
||||
var checker = `url("${canvas.toDataURL()}")`;
|
||||
|
||||
var scrollbar_size = parseInt(getProp("--scrollbar-size"));
|
||||
if (!isFinite(scrollbar_size)) {
|
||||
scrollbar_size = 13;
|
||||
}
|
||||
var scrollbar_button_inner_size = scrollbar_size - 4;
|
||||
|
||||
// I don't know the exact formula, so approximate and special-case it for now
|
||||
// (It may very well *be* special cased, tho)
|
||||
var arrow_size = Math.floor(0.3 * scrollbar_size);
|
||||
if (scrollbar_size < 16 && scrollbar_size > 13) arrow_size -= 1;
|
||||
|
||||
var arrow_width = arrow_size * 2 - 1;
|
||||
|
||||
var arrow_canvas = document.createElement("canvas");
|
||||
var arrow_ctx = arrow_canvas.getContext("2d");
|
||||
arrow_canvas.width = arrow_width;
|
||||
arrow_canvas.height = arrow_size;
|
||||
arrow_ctx.fillStyle = "white";
|
||||
for (let y = 0; y < arrow_size; y += 1) {
|
||||
for (let x = y; x < arrow_width - y; x += 1) {
|
||||
arrow_ctx.fillRect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
canvas.width = scrollbar_button_inner_size * 4;
|
||||
canvas.height = scrollbar_button_inner_size;
|
||||
let i = 0;
|
||||
for (let horizontal = 0; horizontal < 2; horizontal += 1) {
|
||||
for (let decrement = 0; decrement < 2; decrement += 1) {
|
||||
ctx.save();
|
||||
ctx.translate(i * scrollbar_button_inner_size, 0);
|
||||
ctx.translate(scrollbar_button_inner_size / 2, scrollbar_button_inner_size / 2);
|
||||
// ctx.rotate(i * Math.PI / 2);
|
||||
if (horizontal) {
|
||||
ctx.rotate(-Math.PI / 2);
|
||||
}
|
||||
if (decrement) {
|
||||
ctx.scale(1, -1);
|
||||
}
|
||||
ctx.translate(-scrollbar_button_inner_size / 2, -scrollbar_button_inner_size / 2);
|
||||
ctx.drawImage(arrow_canvas, ~~(scrollbar_button_inner_size / 2 - arrow_width / 2), ~~(scrollbar_button_inner_size / 2 - arrow_size / 2));
|
||||
ctx.restore();
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
ctx.globalCompositeOperation = "source-in";
|
||||
ctx.fillStyle = getProp("--ButtonText");
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
var scrollbar_arrows_ButtonText = `url("${canvas.toDataURL()}")`;
|
||||
ctx.fillStyle = getProp("--GrayText");
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
var scrollbar_arrows_GrayText = `url("${canvas.toDataURL()}")`;
|
||||
ctx.fillStyle = getProp("--ButtonHilight");
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
var scrollbar_arrows_ButtonHilight = `url("${canvas.toDataURL()}")`;
|
||||
// ctx.fillStyle = "red";
|
||||
// ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
// canvas.style.background = "rgba(0, 0, 0, 0.2)";
|
||||
// $("h1").append(arrow_canvas).append(canvas);
|
||||
ctx.restore();
|
||||
|
||||
function border_image(border_size, svg_contents) {
|
||||
var base_size = 8;
|
||||
var border_size = border_size;
|
||||
var scale = 32;
|
||||
var slice_size = border_size * scale;
|
||||
var view_size = base_size * scale;
|
||||
// transform causes janky buggy garbage
|
||||
// var svg = `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="${view_size}px" height="${view_size}px" viewBox="0 0 ${view_size} ${view_size}">
|
||||
// <g transform="scale(${scale})">
|
||||
// ${svg_contents}
|
||||
// </g>
|
||||
// </svg>`;
|
||||
var svg = `<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="${view_size}px" height="${view_size}px" viewBox="0 0 ${view_size} ${view_size}">
|
||||
${svg_contents.replace(/(d|x|y|width|height|stroke-width)="[^"]*"/g, (attr) => attr.replace(/\d+/g, (n) => n * scale))}
|
||||
</svg>`;
|
||||
var url = `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
||||
return `url("${url}") ${slice_size} / ${border_size}px`;
|
||||
}
|
||||
|
||||
var button_active_border_image = border_image(2, `
|
||||
<path d="M0 0h8v8h-8v-8z" fill="${getProp("--ButtonDkShadow")}"/>
|
||||
<path d="M1 1h6v6h-6v-6z" fill="${getProp("--ButtonShadow")}"/>
|
||||
<path d="M2 2h4v4h-4v-4z" fill="${getProp("--ButtonFace")}"/>
|
||||
`);
|
||||
var button_default_active_border_image = border_image(2, `
|
||||
<path d="M0 0h8v8h-8v-8z" fill="${getProp("--ButtonDkShadow")}"/>
|
||||
<path d="M1 1h6v6h-6v-6z" fill="${getProp("--ButtonShadow")}"/>
|
||||
<path d="M2 2h4v4h-4v-4z" fill="${getProp("--ButtonFace")}"/>
|
||||
<rect x="0" y="0" width="8" height="8" stroke-width="2" stroke="${getProp("--WindowFrame")}" fill="none"/>
|
||||
`);
|
||||
// TODO: rename
|
||||
var button_normal_border_image = border_image(2, `
|
||||
<path d="M0 0h7v1h-6v6h-1v-7z" fill="${getProp("--ButtonHilight")}"/>
|
||||
<path d="M7 0h1v8h-8v-1h7v-7z" fill="${getProp("--ButtonDkShadow")}"/>
|
||||
<path d="M1 1h5v1h-4v4h-1v-5z" fill="${getProp("--ButtonLight")}"/>
|
||||
<path d="M6 1h1v6h-6v-1h5v-5z" fill="${getProp("--ButtonShadow")}"/>
|
||||
<path d="M2 2h4v4h-4v-4z" fill="${getProp("--ButtonFace")}"/>
|
||||
`);
|
||||
var inset_deep_border_image = border_image(2, `
|
||||
<path d="M0 0h7v1h-6v6h-1v-7z" fill="${getProp("--ButtonDkShadow")}"/>
|
||||
<path d="M7 0h1v8h-8v-1h7v-7z" fill="${getProp("--ButtonHilight")}"/>
|
||||
<path d="M1 1h5v1h-4v4h-1v-5z" fill="${getProp("--ButtonShadow")}"/>
|
||||
<path d="M6 1h1v6h-6v-1h5v-5z" fill="${getProp("--ButtonLight")}"/>
|
||||
<path d="M2 2h4v4h-4v-4z" fill="${getProp("--ButtonFace")}"/>
|
||||
`);
|
||||
var button_default_border_image = border_image(3, `
|
||||
<path d="M0 0h8v8h-8v-8z" fill="${getProp("--ButtonDkShadow")}"/>
|
||||
<path d="M1 1h5v1h-4v4h-1v-5z" fill="${getProp("--ButtonHilight")}"/>
|
||||
<path d="M2 2h3v1h-2v2h-1v-3z" fill="${getProp("--ButtonLight")}"/>
|
||||
<path d="M5 2h1v4h-4v-1h3v-3z" fill="${getProp("--ButtonShadow")}"/>
|
||||
<path d="M3 3h2v2h-2v-2z" fill="${getProp("--ButtonFace")}"/>
|
||||
<rect x="0" y="0" width="8" height="8" stroke-width="2" stroke="${getProp("--WindowFrame")}" fill="none"/>
|
||||
`);
|
||||
|
||||
return {
|
||||
"--checker": checker,
|
||||
"--button-active-border-image": button_active_border_image,
|
||||
"--button-normal-border-image": button_normal_border_image,
|
||||
"--inset-deep-border-image": inset_deep_border_image,
|
||||
"--button-default-border-image": button_default_border_image,
|
||||
"--button-default-active-border-image": button_default_active_border_image,
|
||||
"--scrollbar-arrows-ButtonText": scrollbar_arrows_ButtonText,
|
||||
"--scrollbar-arrows-GrayText": scrollbar_arrows_GrayText,
|
||||
"--scrollbar-arrows-ButtonHilight": scrollbar_arrows_ButtonHilight,
|
||||
"--scrollbar-size": `${scrollbar_size}px`,
|
||||
"--scrollbar-button-inner-size": `${scrollbar_button_inner_size}px`,
|
||||
};
|
||||
}
|
||||
|
||||
function getThemeCSSProperties(element) {
|
||||
const keys = [
|
||||
"--checker",
|
||||
"--button-active-border-image",
|
||||
"--button-normal-border-image",
|
||||
"--inset-deep-border-image",
|
||||
"--button-default-border-image",
|
||||
"--button-default-active-border-image",
|
||||
"--scrollbar-arrows-ButtonText",
|
||||
"--scrollbar-arrows-GrayText",
|
||||
"--scrollbar-arrows-ButtonHilight",
|
||||
"--scrollbar-size",
|
||||
"--scrollbar-button-inner-size",
|
||||
"--ActiveBorder",
|
||||
"--ActiveTitle",
|
||||
"--AppWorkspace",
|
||||
"--Background",
|
||||
"--ButtonAlternateFace",
|
||||
"--ButtonDkShadow",
|
||||
"--ButtonFace",
|
||||
"--ButtonHilight",
|
||||
"--ButtonLight",
|
||||
"--ButtonShadow",
|
||||
"--ButtonText",
|
||||
"--GradientActiveTitle",
|
||||
"--GradientInactiveTitle",
|
||||
"--GrayText",
|
||||
"--Hilight",
|
||||
"--HilightText",
|
||||
"--HotTrackingColor",
|
||||
"--InactiveBorder",
|
||||
"--InactiveTitle",
|
||||
"--InactiveTitleText",
|
||||
"--InfoText",
|
||||
"--InfoWindow",
|
||||
"--Menu",
|
||||
"--MenuText",
|
||||
"--Scrollbar",
|
||||
"--TitleText",
|
||||
"--Window",
|
||||
"--WindowFrame",
|
||||
"--WindowText",
|
||||
];
|
||||
const style = window.getComputedStyle(element);
|
||||
const result = {};
|
||||
for (const key of keys) {
|
||||
result[key] = style.getPropertyValue(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function inheritTheme(target, source) {
|
||||
applyCSSProperties(getThemeCSSProperties(source), { element: target, recurseIntoIframes: true });
|
||||
}
|
||||
|
||||
// Parse NonClientMetrics
|
||||
// https://docs.microsoft.com/en-us/windows/win32/controls/themesfileformat-overview?redirectedfrom=MSDN#metrics-section
|
||||
// https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
|
||||
|
||||
// using https://github.com/toji/js-struct
|
||||
|
||||
// var NonClientMetricsStruct = Struct.create(
|
||||
// Struct.uint32("cbSize"),
|
||||
// Struct.int32("iBorderWidth"),
|
||||
// Struct.int32("iScrollWidth"),
|
||||
// Struct.int32("iScrollHeight"),
|
||||
// Struct.int32("iCaptionWidth"),
|
||||
// Struct.int32("iCaptionHeight"),
|
||||
// // after that, it may be W or A
|
||||
// // LOGFONTW lfCaptionFont;
|
||||
// // int iSmCaptionWidth;
|
||||
// // int iSmCaptionHeight;
|
||||
// // LOGFONTW lfSmCaptionFont;
|
||||
// // int iMenuWidth;
|
||||
// // int iMenuHeight;
|
||||
// // LOGFONTW lfMenuFont;
|
||||
// // LOGFONTW lfStatusFont;
|
||||
// // LOGFONTW lfMessageFont;
|
||||
// // int iPaddedBorderWidth;
|
||||
// );
|
||||
|
||||
// var NonClientMetrics_buffer = new Uint8Array(NonClientMetrics_string.split(" ").map((str)=> parseInt(str))).buffer;
|
||||
|
||||
// NonClientMetricsStruct.readStructs(NonClientMetrics_buffer, 0, 1)[0];
|
||||
|
||||
function parseThemeFileString(themeIni) {
|
||||
// .theme is a renamed .ini text file
|
||||
// .themepack is a renamed .cab file, and parsing it as .ini seems to work well enough for the most part, as the .ini data appears in plain,
|
||||
// but it may not if compression is enabled for the .cab file
|
||||
var theme = parseINIString(themeIni);
|
||||
var colors = theme["Control Panel\\Colors"];
|
||||
if (!colors) {
|
||||
alert("Invalid theme file, no [Control Panel\\Colors] section");
|
||||
console.log(theme);
|
||||
return;
|
||||
}
|
||||
for (var k in colors) {
|
||||
// for .themepack file support, just ignore bad keys that were parsed
|
||||
if (k.match(/\W/)) {
|
||||
delete colors[k];
|
||||
} else {
|
||||
colors[k] = `rgb(${colors[k].split(" ").join(", ")})`;
|
||||
}
|
||||
}
|
||||
|
||||
var cssProperties = {};
|
||||
for (var k in colors) {
|
||||
cssProperties[`--${k}`] = colors[k];
|
||||
}
|
||||
|
||||
cssProperties = Object.assign(renderThemeGraphics(cssProperties), cssProperties);
|
||||
|
||||
return cssProperties;
|
||||
}
|
||||
|
||||
function applyCSSProperties(cssProperties, options = {}) {
|
||||
// @TODO: clean up deprecated argument handling
|
||||
let element, recurseIntoIframes;
|
||||
if ("tagName" in options) {
|
||||
console.warn("deprecated: use options argument to applyCSSProperties, e.g. applyCSSProperties(cssProperties, { element: document.documentElement, recurseIntoIframes: true })");
|
||||
element = options;
|
||||
recurseIntoIframes = false;
|
||||
} else {
|
||||
({ element = document.documentElement, recurseIntoIframes = false } = options);
|
||||
}
|
||||
|
||||
var getProp = (propName) => cssProperties.getPropertyValue ? cssProperties.getPropertyValue(propName) : cssProperties[propName];
|
||||
for (var k in cssProperties) {
|
||||
element.style.setProperty(k, getProp(k));
|
||||
}
|
||||
// iframe theme propagation
|
||||
if (recurseIntoIframes) {
|
||||
var iframes = element.querySelectorAll("iframe");
|
||||
for (var i = 0; i < iframes.length; i++) {
|
||||
try {
|
||||
applyCSSProperties(cssProperties, { element: iframes[i].contentDocument.documentElement, recurseIntoIframes: true });
|
||||
} catch (error) {
|
||||
// ignore
|
||||
// @TODO: share warning with $Window's iframe handling
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeThemeCSSFile(cssProperties) {
|
||||
var css = `
|
||||
/* This is a generated file. */
|
||||
:root {
|
||||
`;
|
||||
for (var k in cssProperties) {
|
||||
css += `\t${k}: ${cssProperties[k]};\n`;
|
||||
}
|
||||
css += `}
|
||||
`;
|
||||
return css;
|
||||
}
|
||||
|
||||
// @TODO: should this be part of theme graphics generation?
|
||||
// I want to figure out a better way to do dynamic theme features,
|
||||
// where it works with the CSS cascade as much as possible
|
||||
function makeBlackToInsetFilter() {
|
||||
if (document.getElementById("os-gui-black-to-inset-filter")) {
|
||||
return;
|
||||
}
|
||||
const svg_xml = `
|
||||
<svg style="position: absolute; pointer-events: none; bottom: 100%;">
|
||||
<defs>
|
||||
<filter id="os-gui-black-to-inset-filter" x="0" y="0" width="1px" height="1px">
|
||||
<feColorMatrix
|
||||
in="SourceGraphic"
|
||||
type="matrix"
|
||||
values="
|
||||
1 0 0 0 0
|
||||
0 1 0 0 0
|
||||
0 0 1 0 0
|
||||
-1000 -1000 -1000 1 0
|
||||
"
|
||||
result="black-parts-isolated"
|
||||
/>
|
||||
<feFlood result="shadow-color" flood-color="var(--ButtonShadow)"/>
|
||||
<feFlood result="hilight-color" flood-color="var(--ButtonHilight)"/>
|
||||
<feOffset in="black-parts-isolated" dx="1" dy="1" result="offset"/>
|
||||
<feComposite in="hilight-color" in2="offset" operator="in" result="hilight-colored-offset"/>
|
||||
<feComposite in="shadow-color" in2="black-parts-isolated" operator="in" result="shadow-colored"/>
|
||||
<feMerge>
|
||||
<feMergeNode in="hilight-colored-offset"/>
|
||||
<feMergeNode in="shadow-colored"/>
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
`;
|
||||
const $svg = $(svg_xml);
|
||||
$svg.appendTo("body");
|
||||
}
|
||||
49
static/html/jspaint/lib/os-gui/peggys-pastels.css
Normal file
49
static/html/jspaint/lib/os-gui/peggys-pastels.css
Normal file
@@ -0,0 +1,49 @@
|
||||
/* Source: https://www.deviantart.com/tpenguinltg/art/Peggy-s-Pastels-505540096 */
|
||||
/* License: https://creativecommons.org/licenses/by-sa/3.0/ */
|
||||
/* This is a generated file. */
|
||||
:root {
|
||||
--checker: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2P89eDJ/18PnzEwfjl46j+bvBQDAHJ8Cj5el2f8AAAAAElFTkSuQmCC");
|
||||
--button-active-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22rgb(64%2C%2064%2C%2064)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22rgb(222%2C%2069%2C%2096)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22rgb(244%2C%20193%2C%20202)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--button-normal-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22rgb(250%2C%20224%2C%20228)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22rgb(64%2C%2064%2C%2064)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22rgb(247%2C%20219%2C%20215)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22rgb(222%2C%2069%2C%2096)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22rgb(244%2C%20193%2C%20202)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--inset-deep-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22rgb(64%2C%2064%2C%2064)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22rgb(250%2C%20224%2C%20228)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22rgb(222%2C%2069%2C%2096)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22rgb(247%2C%20219%2C%20215)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22rgb(244%2C%20193%2C%20202)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--button-default-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22rgb(64%2C%2064%2C%2064)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22rgb(250%2C%20224%2C%20228)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h96v32h-64v64h-32v-96z%22%20fill%3D%22rgb(247%2C%20219%2C%20215)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M160%2064h32v128h-128v-32h96v-96z%22%20fill%3D%22rgb(222%2C%2069%2C%2096)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M96%2096h64v64h-64v-64z%22%20fill%3D%22rgb(244%2C%20193%2C%20202)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 96 / 3px;
|
||||
--button-default-active-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22rgb(64%2C%2064%2C%2064)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22rgb(222%2C%2069%2C%2096)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22rgb(244%2C%20193%2C%20202)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--scrollbar-arrows-ButtonText: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAW0lEQVQ4T2NkGGSAcZC5h4FWDvrPwEC02ShqkR0EkkAHuBxMyEKYWYQ8jKEOXQOyo/A5BuZwqqvBZiA+3xMbilQLIWqlcUJRimwPzjRELcdQZA6hREeR4eRoBgBoXhAK6oiMhwAAAABJRU5ErkJggg==");
|
||||
--scrollbar-arrows-GrayText: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDrrnmvBfafcCosxGVwvXBJJADy1chhKyEGYWIUdhU4fiC2RH4XMMzOG0UIMRrPh8T2woUi2EqJXACUUpsj040xC1HEOpOUTlBEotIUU/ANEWQAoG78U6AAAAAElFTkSuQmCC");
|
||||
--scrollbar-arrows-ButtonHilight: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDvr14Ml/NgUZosxGVwvXBJJADy1chhKyEGYWIUdhU4fiC2RH4XMMzOG0UIMRrPh8T2woUi2EqJXACUUpsj040xC1HEOpOUTlBEotIUU/AIJVQAqPLmKjAAAAAElFTkSuQmCC");
|
||||
--scrollbar-size: 13px;
|
||||
--scrollbar-button-inner-size: 9px;
|
||||
--Scrollbar: rgb(250, 224, 228);
|
||||
--Background: rgb(162, 219, 210);
|
||||
--ActiveTitle: rgb(0, 191, 188);
|
||||
--InactiveTitle: rgb(0, 187, 169);
|
||||
--Menu: rgb(244, 193, 202);
|
||||
--Window: rgb(244, 255, 255);
|
||||
--WindowFrame: rgb(0, 0, 0);
|
||||
--MenuText: rgb(0, 0, 0);
|
||||
--WindowText: rgb(0, 0, 0);
|
||||
--TitleText: rgb(255, 255, 255);
|
||||
--ActiveBorder: rgb(244, 193, 202);
|
||||
--InactiveBorder: rgb(244, 193, 202);
|
||||
--AppWorkspace: rgb(255, 184, 182);
|
||||
--Hilight: rgb(162, 219, 210);
|
||||
--HilightText: rgb(0, 0, 0);
|
||||
--ButtonFace: rgb(244, 193, 202);
|
||||
--ButtonShadow: rgb(222, 69, 96);
|
||||
--GrayText: rgb(222, 69, 96);
|
||||
--ButtonText: rgb(0, 0, 0);
|
||||
--InactiveTitleText: rgb(0, 85, 77);
|
||||
--ButtonHilight: rgb(250, 224, 228);
|
||||
--ButtonDkShadow: rgb(64, 64, 64);
|
||||
--ButtonLight: rgb(247, 219, 215);
|
||||
--InfoText: rgb(0, 0, 0);
|
||||
--InfoWindow: rgb(204, 255, 255);
|
||||
--ButtonAlternateFace: rgb(181, 181, 181);
|
||||
--HotTrackingColor: rgb(0, 128, 128);
|
||||
--GradientActiveTitle: rgb(202, 156, 185);
|
||||
--GradientInactiveTitle: rgb(236, 145, 162);
|
||||
--MenuHilight: rgb(162, 219, 210);
|
||||
--MenuBar: rgb(244, 193, 202);
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=peggys-pastels.css.map */
|
||||
1
static/html/jspaint/lib/os-gui/peggys-pastels.css.map
Normal file
1
static/html/jspaint/lib/os-gui/peggys-pastels.css.map
Normal file
File diff suppressed because one or more lines are too long
993
static/html/jspaint/lib/os-gui/windows-98.css
Normal file
993
static/html/jspaint/lib/os-gui/windows-98.css
Normal file
@@ -0,0 +1,993 @@
|
||||
:root {
|
||||
/* These resources are generated. */
|
||||
/* JS: makeThemeCSSFile(renderThemeGraphics(getComputedStyle(document.documentElement))) */
|
||||
--checker: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2P8/////4MHDzIwHjhw4L+9vT0DAHAFCj6esq3FAAAAAElFTkSuQmCC");
|
||||
--button-active-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--button-normal-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--inset-deep-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--button-default-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h96v32h-64v64h-32v-96z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M160%2064h32v128h-128v-32h96v-96z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M96%2096h64v64h-64v-64z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22%20rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 96 / 3px;
|
||||
--button-default-active-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22%20rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--scrollbar-arrows-ButtonText: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAW0lEQVQ4T2NkGGSAcZC5h4FWDvrPwEC02ShqkR0EkkAHuBxMyEKYWYQ8jKEOXQOyo/A5BuZwqqvBZiA+3xMbilQLIWqlcUJRimwPzjRELcdQZA6hREeR4eRoBgBoXhAK6oiMhwAAAABJRU5ErkJggg==");
|
||||
--scrollbar-arrows-GrayText: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDmpoaPjf0NBAlNnoauGaQBLooYXLUEIWwswi5Chs6lB8gewofI6BOZwWajCCFZ/viQ1FqoUQtRI4oShFtgdnGqKWYyg1h6icQKklpOgHAM9mQArEvm5+AAAAAElFTkSuQmCC");
|
||||
--scrollbar-arrows-ButtonHilight: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDvr///9/RkZGosxGVwvXBJJADy1chhKyEGYWIUdhU4fiC2RH4XMMzOG0UIMRrPh8T2woUi2EqJXACUUpsj040xC1HEOpOUTlBEotIUU/AKXFQAqyTJ6DAAAAAElFTkSuQmCC");
|
||||
--scrollbar-size: 13px;
|
||||
--scrollbar-button-inner-size: 9px;
|
||||
|
||||
/* Colors */
|
||||
--ActiveBorder: rgb(192, 192, 192);
|
||||
--ActiveTitle: rgb(0, 0, 128);
|
||||
--AppWorkspace: rgb(128, 128, 128);
|
||||
--Background: rgb(0, 128, 128);
|
||||
--ButtonAlternateFace: rgb(180, 180, 180);
|
||||
--ButtonDkShadow: rgb(0, 0, 0);
|
||||
--ButtonFace: rgb(192, 192, 192);
|
||||
--ButtonHilight: rgb(255, 255, 255);
|
||||
--ButtonLight: rgb(223, 223, 223);
|
||||
--ButtonShadow: rgb(128, 128, 128);
|
||||
--ButtonText: rgb(0, 0, 0);
|
||||
--GradientActiveTitle: rgb(16, 132, 208);
|
||||
--GradientInactiveTitle: rgb(181, 181, 181);
|
||||
--GrayText: rgb(128, 128, 128);
|
||||
--Hilight: rgb(0, 0, 128);
|
||||
--HilightText: rgb(255, 255, 255);
|
||||
--HotTrackingColor: rgb(0, 0, 255);
|
||||
--InactiveBorder: rgb(192, 192, 192);
|
||||
--InactiveTitle: rgb(128, 128, 128);
|
||||
--InactiveTitleText: rgb(192, 192, 192);
|
||||
--InfoText: rgb(0, 0, 0);
|
||||
--InfoWindow: rgb(255, 255, 225);
|
||||
--Menu: rgb(192, 192, 192);
|
||||
--MenuText: rgb(0, 0, 0);
|
||||
--Scrollbar: rgb(192, 192, 192);
|
||||
--TitleText: rgb(255, 255, 255);
|
||||
--Window: rgb(255, 255, 255);
|
||||
--WindowFrame: rgb(0, 0, 0);
|
||||
--WindowText: rgb(0, 0, 0);
|
||||
}
|
||||
|
||||
.inset-deep {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(128, 128, 128) rgb(255, 255, 255) rgb(255, 255, 255) rgb(128, 128, 128);
|
||||
border-color: var(--ButtonShadow) var(--ButtonHilight) var(--ButtonHilight) var(--ButtonShadow);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
/* as fallback */
|
||||
position: relative;
|
||||
/* for pseudo element(s) */
|
||||
-o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
-o-border-image: var(--inset-deep-border-image);
|
||||
border-image: var(--inset-deep-border-image);
|
||||
border-color: rgb(128, 128, 128);
|
||||
border-color: var(--ButtonShadow);
|
||||
border-style: solid;
|
||||
border-width: 2px 2px;
|
||||
}
|
||||
.outset-deep {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(255, 255, 255) rgb(128, 128, 128) rgb(128, 128, 128) rgb(255, 255, 255);
|
||||
border-color: var(--ButtonHilight) var(--ButtonShadow) var(--ButtonShadow) var(--ButtonHilight);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
/* as fallback */
|
||||
position: relative;
|
||||
/* for pseudo element(s) */
|
||||
-o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
-o-border-image: var(--button-normal-border-image);
|
||||
border-image: var(--button-normal-border-image);
|
||||
border-color: rgb(223, 223, 223) rgb(128, 128, 128) rgb(128, 128, 128) rgb(223, 223, 223);
|
||||
border-color: var(--ButtonLight) var(--ButtonShadow) var(--ButtonShadow) var(--ButtonLight);
|
||||
border-style: solid;
|
||||
border-width: 2px 2px;
|
||||
}
|
||||
.inset-shallow {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(128, 128, 128) rgb(255, 255, 255) rgb(255, 255, 255) rgb(128, 128, 128);
|
||||
border-color: var(--ButtonShadow) var(--ButtonHilight) var(--ButtonHilight) var(--ButtonShadow);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
}
|
||||
.outset-shallow {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(255, 255, 255) rgb(128, 128, 128) rgb(128, 128, 128) rgb(255, 255, 255);
|
||||
border-color: var(--ButtonHilight) var(--ButtonShadow) var(--ButtonShadow) var(--ButtonHilight);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
}
|
||||
button:not(.lightweight) {
|
||||
outline: none; /* replaced with inner dotted focus ring (which is admittedly not so prominent...) */ border-style: solid; border-width: 1px; border-color: rgb(255, 255, 255) rgb(128, 128, 128) rgb(128, 128, 128) rgb(255, 255, 255); border-color: var(--ButtonHilight) var(--ButtonShadow) var(--ButtonShadow) var(--ButtonHilight); background-color: rgb(192, 192, 192); background-color: var(--ButtonFace); color: rgb(0, 0, 0); color: var(--ButtonText); /* as fallback */ position: relative; /* for pseudo element(s) */ -o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px; border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px; -o-border-image: var(--button-normal-border-image); border-image: var(--button-normal-border-image); border-color: rgb(223, 223, 223) rgb(128, 128, 128) rgb(128, 128, 128) rgb(223, 223, 223); border-color: var(--ButtonLight) var(--ButtonShadow) var(--ButtonShadow) var(--ButtonLight); border-style: solid; border-width: 2px 2px; border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px; border-image: var(--button-normal-border-image);
|
||||
}
|
||||
button:not(.lightweight).default {
|
||||
-o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h96v32h-64v64h-32v-96z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M160%2064h32v128h-128v-32h96v-96z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M96%2096h64v64h-64v-64z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22%20rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 96 / 3px;
|
||||
border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h96v32h-64v64h-32v-96z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M160%2064h32v128h-128v-32h96v-96z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M96%2096h64v64h-64v-64z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22%20rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 96 / 3px;
|
||||
-o-border-image: var(--button-default-border-image);
|
||||
border-image: var(--button-default-border-image);
|
||||
}
|
||||
button:not(.lightweight):enabled:hover:active {
|
||||
-o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
-o-border-image: var(--button-active-border-image);
|
||||
border-image: var(--button-active-border-image);
|
||||
}
|
||||
button:not(.lightweight).default:enabled:hover:active {
|
||||
-o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22%20rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22%20rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
-o-border-image: var(--button-default-active-border-image);
|
||||
border-image: var(--button-default-active-border-image);
|
||||
}
|
||||
|
||||
/* TODO: offset content on press! */
|
||||
/* (this would need a child ELEMENT, wouldn't work with text nodes as direct descendants:) */
|
||||
/*button:active > * {
|
||||
position: relative;
|
||||
left: 1px;
|
||||
top: 1px;
|
||||
}
|
||||
*/
|
||||
/* also, this is more complicated; see Paint; the tool buttons translate when being pushed and when depressed, and these add together */
|
||||
/* omg, a thought... what if I used feDisplacementMap SVG filter... */
|
||||
|
||||
button:not(.lightweight):focus::before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
border: 1px dotted rgb(0, 0, 0);
|
||||
border: 1px dotted var(--ButtonDkShadow); /* ?? */
|
||||
/* TODO: get exact inset dimensions, and have corners without dots ideally */
|
||||
/* (could use outline instead of ::before at this point) */
|
||||
}
|
||||
button.lightweight {
|
||||
outline: none; /* these buttons are not usually keyboard accessible, or the focus it shown just by inset (menu buttons) */
|
||||
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: transparent;
|
||||
}
|
||||
/* TODO: recommend preventing focus on click for lightweight buttons */
|
||||
button.lightweight:enabled:hover {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(255, 255, 255) rgb(128, 128, 128) rgb(128, 128, 128) rgb(255, 255, 255);
|
||||
border-color: var(--ButtonHilight) var(--ButtonShadow) var(--ButtonShadow) var(--ButtonHilight);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
}
|
||||
button.lightweight:enabled:hover:active, button.lightweight.pressing, button.lightweight.pressed {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(128, 128, 128) rgb(255, 255, 255) rgb(255, 255, 255) rgb(128, 128, 128);
|
||||
border-color: var(--ButtonShadow) var(--ButtonHilight) var(--ButtonHilight) var(--ButtonShadow);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
}
|
||||
button:disabled {
|
||||
color: rgb(128, 128, 128);
|
||||
color: var(--GrayText);
|
||||
text-shadow: 1px 1px 0px rgb(255, 255, 255);
|
||||
text-shadow: 1px 1px 0px var(--ButtonHilight);
|
||||
}
|
||||
button:not(.lightweight).toggle:enabled:hover:active, button:not(.lightweight).pressing {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(128, 128, 128) rgb(255, 255, 255) rgb(255, 255, 255) rgb(128, 128, 128);
|
||||
border-color: var(--ButtonShadow) var(--ButtonHilight) var(--ButtonHilight) var(--ButtonShadow);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
/* as fallback */
|
||||
position: relative;
|
||||
/* for pseudo element(s) */
|
||||
-o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
-o-border-image: var(--inset-deep-border-image);
|
||||
border-image: var(--inset-deep-border-image);
|
||||
}
|
||||
button:not(.lightweight).toggle:enabled:hover:active, button:not(.lightweight).pressing {
|
||||
border-color: rgb(128, 128, 128);
|
||||
border-color: var(--ButtonShadow);
|
||||
border-style: solid;
|
||||
border-width: 2px 2px;
|
||||
}
|
||||
button:not(.lightweight).toggle.selected, button:not(.lightweight).pressed {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(128, 128, 128) rgb(255, 255, 255) rgb(255, 255, 255) rgb(128, 128, 128);
|
||||
border-color: var(--ButtonShadow) var(--ButtonHilight) var(--ButtonHilight) var(--ButtonShadow);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
/* as fallback */
|
||||
position: relative;
|
||||
/* for pseudo element(s) */
|
||||
-o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
-o-border-image: var(--inset-deep-border-image);
|
||||
border-image: var(--inset-deep-border-image);
|
||||
}
|
||||
button:not(.lightweight).toggle.selected, button:not(.lightweight).pressed {
|
||||
border-color: rgb(128, 128, 128);
|
||||
border-color: var(--ButtonShadow);
|
||||
border-style: solid;
|
||||
border-width: 2px 2px;
|
||||
}
|
||||
button:not(.lightweight).toggle.selected, button:not(.lightweight).pressed {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2P8/////4MHDzIwHjhw4L+9vT0DAHAFCj6esq3FAAAAAElFTkSuQmCC") repeat;
|
||||
background: var(--checker) repeat;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.os-window .window-titlebar,
|
||||
body > .window-titlebar {
|
||||
background: rgb(0, 0, 128);
|
||||
background: var(--ActiveTitle);
|
||||
background: linear-gradient(to right, rgb(0, 0, 128) 0%, rgb(16, 132, 208) 100%);
|
||||
background: linear-gradient(to right, var(--ActiveTitle) 0%, var(--GradientActiveTitle) 100%);
|
||||
|
||||
color: rgb(255, 255, 255);
|
||||
|
||||
color: var(--TitleText);
|
||||
}
|
||||
|
||||
.os-window .window-titlebar, body > .window-titlebar {
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
.os-window.rtl .window-titlebar {
|
||||
background: linear-gradient(to left, rgb(0, 0, 128) 0%, rgb(16, 132, 208) 100%);
|
||||
background: linear-gradient(to left, var(--ActiveTitle) 0%, var(--GradientActiveTitle) 100%);
|
||||
}
|
||||
.os-window:not(.tool-window) .window-titlebar,
|
||||
body > .window-titlebar {
|
||||
font-weight: bold;
|
||||
}
|
||||
.os-window:not(.focused) .window-titlebar {
|
||||
background: darkgray;
|
||||
background: linear-gradient(to right, rgb(128, 128, 128) 0%, rgb(181, 181, 181) 100%);
|
||||
background: linear-gradient(to right, var(--InactiveTitle) 0%, var(--GradientInactiveTitle) 100%);
|
||||
|
||||
color: rgb(192, 192, 192);
|
||||
|
||||
color: var(--InactiveTitleText);
|
||||
}
|
||||
.os-window.rtl:not(.focused) .window-titlebar {
|
||||
background: linear-gradient(to left, rgb(128, 128, 128) 0%, rgb(181, 181, 181) 100%);
|
||||
background: linear-gradient(to left, var(--InactiveTitle) 0%, var(--GradientInactiveTitle) 100%);
|
||||
}
|
||||
.os-window {
|
||||
/* Needed for when maximized, otherwise would be provided by %outset-deep */
|
||||
background: rgb(192, 192, 192);
|
||||
background: var(--ButtonFace);
|
||||
|
||||
/* background: var(--Window); */
|
||||
/*color: var(--WindowText);*/
|
||||
/*border: 1px solid var(--WindowFrame);*/
|
||||
/* TODO: use window-specific theme colors; also different types of windows */
|
||||
}
|
||||
.os-window:not(.maximized) {
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: rgb(255, 255, 255) rgb(128, 128, 128) rgb(128, 128, 128) rgb(255, 255, 255);
|
||||
border-color: var(--ButtonHilight) var(--ButtonShadow) var(--ButtonShadow) var(--ButtonHilight);
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--ButtonText);
|
||||
/* as fallback */
|
||||
position: relative;
|
||||
/* for pseudo element(s) */
|
||||
-o-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
-o-border-image: var(--button-normal-border-image);
|
||||
border-image: var(--button-normal-border-image);
|
||||
border-color: rgb(223, 223, 223) rgb(128, 128, 128) rgb(128, 128, 128) rgb(223, 223, 223);
|
||||
border-color: var(--ButtonLight) var(--ButtonShadow) var(--ButtonShadow) var(--ButtonLight);
|
||||
border-style: solid;
|
||||
border-width: 2px 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.window-button {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 14px;
|
||||
padding: 0;
|
||||
margin: 2px 0;
|
||||
}
|
||||
.window-button-icon {
|
||||
display: block;
|
||||
/* background-image: url("images/titlebar-buttons.png"); */
|
||||
--sprite-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAAKCAYAAADo3z3CAAAAoUlEQVRIS9VVWw7AIAib9z/0FpZgCOFRgpluf9MClhYdV++7gfDhYLxYDw+UyiHd5F8S5lr6zNa6Xpv/KwhHOahQpLB1+CwfycgYrwmE0WK8MTsIR1aOGsR+NYkkYzN5/pGwVA9xA/diq8LeHCKuQxQ+aoYt2yJWtpSNZth0edRpGVC5eGQcSg4hXLml3fdpBeHs8evWyPKX9ruXVqnYCeAHA8IyC9K2kmkAAAAASUVORK5CYII=");
|
||||
--sprite-y: 0;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
width: 12px;
|
||||
height: 10px;
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
}
|
||||
.os-window .window-button:enabled:hover:active .window-button-icon,
|
||||
.os-window .window-button.pressing .window-button-icon {
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
}
|
||||
.window-button:disabled .window-button-icon {
|
||||
/* filter: saturate(0%) opacity(50%); fallback */
|
||||
/* filter: url("#os-gui-black-to-inset-filter"); */
|
||||
}
|
||||
.window-button .window-button-icon::before,
|
||||
.window-button .window-button-icon::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
-webkit-mask-image: var(--sprite-image);
|
||||
mask-image: var(--sprite-image);
|
||||
-webkit-mask-position: var(--sprite-x) var(--sprite-y);
|
||||
mask-position: var(--sprite-x) var(--sprite-y);
|
||||
background-color: rgb(0, 0, 0);
|
||||
background-color: var(--ButtonText);
|
||||
}
|
||||
.window-button:disabled .window-button-icon::before {
|
||||
background-color: rgb(255, 255, 255);
|
||||
background-color: var(--ButtonHilight);
|
||||
left: 1px;
|
||||
top: 1px;
|
||||
}
|
||||
.window-button:enabled .window-button-icon::after {
|
||||
display: none;
|
||||
}
|
||||
.window-button:disabled .window-button-icon::after {
|
||||
background-color: rgb(128, 128, 128);
|
||||
background-color: var(--GrayText);
|
||||
}
|
||||
.window-action-close .window-button-icon {
|
||||
--sprite-x: calc(-3 * 13px - 1px);
|
||||
}
|
||||
.window-action-maximize .window-button-icon {
|
||||
--sprite-x: calc(-1 * 13px - 1px);
|
||||
}
|
||||
.window-action-restore .window-button-icon {
|
||||
--sprite-x: calc(-2 * 13px - 1px);
|
||||
}
|
||||
.window-action-minimize .window-button-icon {
|
||||
--sprite-x: calc(-0 * 13px - 1px);
|
||||
}
|
||||
.window-close-button {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.os-window.tool-window .window-close-button {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
}
|
||||
.os-window.tool-window .window-close-button .window-button-icon {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
--sprite-x: 7px;
|
||||
}
|
||||
.os-window .window-title-area {
|
||||
height: 16px;
|
||||
}
|
||||
.os-window.tool-window .window-title-area {
|
||||
height: 14px;
|
||||
}
|
||||
.os-window .window-titlebar {
|
||||
height: 18px;
|
||||
}
|
||||
.os-window.tool-window .window-titlebar {
|
||||
height: 15px;
|
||||
}
|
||||
.os-window .window-title {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: inline-block !important;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
padding-left: 2px;
|
||||
}
|
||||
|
||||
.menus {
|
||||
background: rgb(192, 192, 192);
|
||||
background: var(--Menu);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--MenuText);
|
||||
}
|
||||
.os-window:not(.focused) .menus {
|
||||
color: rgb(128, 128, 128);
|
||||
color: var(--GrayText);
|
||||
}
|
||||
.menus *, .menu-popup * {
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
.menu-button {
|
||||
box-sizing: border-box;
|
||||
/* Using a balanced border to offset the contents on press */
|
||||
border: 0px solid transparent;
|
||||
border-top-width: 0px;
|
||||
border-left-width: 0px;
|
||||
border-bottom-width: 1px;
|
||||
border-right-width: 1px;
|
||||
/* Unfortunately, everything else has to be balanced by 1px (very carefully) in many places. */
|
||||
|
||||
height: 18px; /* (EFFECTIVELY NORMAL but...) +1px -1px: +1px due to transparent border, but needs to be metrically same as visual height for the menu popup positioning, so I used bottom: -1px on the pseudo element to get it so this can be -1px to 18px again */
|
||||
line-height: 1;
|
||||
margin-top: 1px; /* NORMAL MARGIN */
|
||||
/* margin-bottom: 1px; consumed margin */
|
||||
margin-right: -1px; /* keep menu items directly abutting */
|
||||
|
||||
/* need the overflow visible for the psuedo element's top and left borders to be visible */
|
||||
overflow: visible;
|
||||
-webkit-clip-path: inset(0 1px 0 0);
|
||||
clip-path: inset(0 1px 0 0); /* clipping text off inside the border, without clipping the border (somewhat mysteriously) */
|
||||
|
||||
padding: 2px 5px; /* NORMAL PADDING; I took great lengths to make this easily changable from outside code (padding is an obvious strategy for making the press offset effect, but I think this is a common thing you might want to customize) */
|
||||
position: relative;
|
||||
outline: 0;
|
||||
/* @extend button.lightweight; */
|
||||
background: rgb(192, 192, 192);
|
||||
background: var(--Menu);
|
||||
}
|
||||
.menu-button.highlight.active {
|
||||
border-top-width: 1px;
|
||||
border-left-width: 1px;
|
||||
border-bottom-width: 0px;
|
||||
border-right-width: 0px;
|
||||
}
|
||||
/* Note: In Windows 98, normal menu bars have an inset highlight if you use Esc and then the arrow keys,
|
||||
whereas Explorer's menu bars are outset and match the hover effect, which I feel makes more sense,
|
||||
so I think I'll immitate that. */
|
||||
/* Also, to prevent duplicate highlight (via keyboard + mouse), and lingering highlight with touch, I'm using a class, rather than :hover/:focus/:active */
|
||||
.menu-button.highlight::after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: -1px;
|
||||
box-shadow: 1px 1px 0 rgb(255, 255, 255) inset, -1px -1px 0 rgb(128, 128, 128) inset;
|
||||
box-shadow: 1px 1px 0 var(--ButtonHilight) inset, -1px -1px 0 var(--ButtonShadow) inset;
|
||||
}
|
||||
.menu-button.highlight.active::after {
|
||||
box-shadow: 1px 1px 0 rgb(128, 128, 128) inset, -1px -1px 0 rgb(255, 255, 255) inset;
|
||||
box-shadow: 1px 1px 0 var(--ButtonShadow) inset, -1px -1px 0 var(--ButtonHilight) inset;
|
||||
/* counteract the balanced border, in order to render this border, in the proper place */
|
||||
left: -1px;
|
||||
top: -1px;
|
||||
right: 1px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.menu-popup {
|
||||
display: block;
|
||||
padding: 2px;
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
border-top: 1px solid rgb(192, 192, 192);
|
||||
border-top: 1px solid var(--ButtonFace);
|
||||
border-left: 1px solid rgb(192, 192, 192);
|
||||
border-left: 1px solid var(--ButtonFace);
|
||||
border-right: 1px solid rgb(0, 0, 0);
|
||||
border-right: 1px solid var(--ButtonDkShadow);
|
||||
border-bottom: 1px solid rgb(0, 0, 0);
|
||||
border-bottom: 1px solid var(--ButtonDkShadow);
|
||||
box-shadow: 1px 1px 0 rgb(255, 255, 255) inset, -1px -1px 0 rgb(128, 128, 128) inset;
|
||||
box-shadow: 1px 1px 0 var(--ButtonHilight) inset, -1px -1px 0 var(--ButtonShadow) inset;
|
||||
background: rgb(192, 192, 192);
|
||||
background: var(--Menu);
|
||||
color: rgb(0, 0, 0);
|
||||
color: var(--MenuText);
|
||||
}
|
||||
.menu-popup td {
|
||||
padding: 0 1px;
|
||||
}
|
||||
.menu-item {
|
||||
padding: 1px 3px;
|
||||
margin: 2px;
|
||||
height: 17px;
|
||||
}
|
||||
.menu-item[disabled] {
|
||||
color: rgb(128, 128, 128);
|
||||
color: var(--GrayText);
|
||||
text-shadow: 0.8px 0.8px 0px rgb(255, 255, 255);
|
||||
text-shadow: 0.8px 0.8px 0px var(--ButtonHilight);
|
||||
}
|
||||
.menu-item.highlight:not([disabled]),
|
||||
.menu-item.active:not([disabled]) {
|
||||
color: rgb(255, 255, 255);
|
||||
color: var(--HilightText);
|
||||
}
|
||||
.menu-item.highlight,
|
||||
.menu-item.active {
|
||||
background: rgb(0, 0, 128);
|
||||
background: var(--Hilight);
|
||||
text-shadow: none;
|
||||
outline: 0;
|
||||
}
|
||||
.menu-item .menu-item-shortcut {
|
||||
padding-left: 10px;
|
||||
}
|
||||
/* Note: viewBox is needed for scaling the SVG, used in JS Paint's Eye Gaze Mode */
|
||||
.menu-item-checkbox-area::after {
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' style='fill:currentColor;display:inline-block;vertical-align:middle' %3E%3Cpath d='M5 7v3l2 2 5-5V4L7 9Z'/%3E%3C/svg%3E");
|
||||
mask-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' style='fill:currentColor;display:inline-block;vertical-align:middle' %3E%3Cpath d='M5 7v3l2 2 5-5V4L7 9Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
.menu-item-checkbox-area.radio::after {
|
||||
-webkit-mask-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' style='fill:currentColor;display:inline-block;vertical-align:middle' %3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E");
|
||||
mask-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' style='fill:currentColor;display:inline-block;vertical-align:middle' %3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E");
|
||||
}
|
||||
.has-submenu .menu-item-submenu-area::after {
|
||||
-webkit-mask-image: url("data:image/svg+xml, %3Csvg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' style='fill:currentColor;display:inline-block;vertical-align:middle' %3E%3Cpath d='m6 4 4 4-4 4z'/%3E%3C/svg%3E");
|
||||
mask-image: url("data:image/svg+xml, %3Csvg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' style='fill:currentColor;display:inline-block;vertical-align:middle' %3E%3Cpath d='m6 4 4 4-4 4z'/%3E%3C/svg%3E");
|
||||
}
|
||||
.has-submenu .menu-item-submenu-area.point-right::after {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
.menu-item-checkbox-area::after,
|
||||
.menu-item-submenu-area::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
/* no background means it's invisible by default here (masking transparent gives transparent, i.e. nothing) */
|
||||
}
|
||||
.menu-item[aria-checked=true] .menu-item-checkbox-area::after,
|
||||
.menu-item.has-submenu .menu-item-submenu-area::after {
|
||||
/* makes it visible */
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.menu-hr {
|
||||
border: 0;
|
||||
border-top: 1px solid rgb(128, 128, 128);
|
||||
border-top: 1px solid var(--ButtonShadow);
|
||||
border-bottom: 1px solid rgb(255, 255, 255);
|
||||
border-bottom: 1px solid var(--ButtonHilight);
|
||||
margin: 0;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.menu-hotkey {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.menu-hotkey::-moz-selection {
|
||||
/* prevent weird looking white underlines if menubar is contained in a selection, possible in the demo (minute edge case) */
|
||||
text-decoration-color: rgb(0, 0, 0) !important;
|
||||
text-decoration-color: var(--MenuText) !important;
|
||||
}
|
||||
.menu-hotkey::selection {
|
||||
/* prevent weird looking white underlines if menubar is contained in a selection, possible in the demo (minute edge case) */
|
||||
-webkit-text-decoration-color: rgb(0, 0, 0) !important;
|
||||
text-decoration-color: rgb(0, 0, 0) !important;
|
||||
-webkit-text-decoration-color: var(--MenuText) !important;
|
||||
text-decoration-color: var(--MenuText) !important;
|
||||
}
|
||||
|
||||
|
||||
::-moz-selection {
|
||||
background-color: rgb(0, 0, 128);
|
||||
background-color: var(--Hilight);
|
||||
color: rgb(255, 255, 255);
|
||||
color: var(--HilightText);
|
||||
}
|
||||
|
||||
|
||||
::selection {
|
||||
background-color: rgb(0, 0, 128);
|
||||
background-color: var(--Hilight);
|
||||
color: rgb(255, 255, 255);
|
||||
color: var(--HilightText);
|
||||
}
|
||||
|
||||
.scrollbar {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2P8/////4MHDzIwHjhw4L+9vT0DAHAFCj6esq3FAAAAAElFTkSuQmCC") repeat;
|
||||
background: var(--checker) repeat;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
.scrollbar-thumb {
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
border-top: 1px solid rgb(192, 192, 192);
|
||||
border-top: 1px solid var(--ButtonFace);
|
||||
border-left: 1px solid rgb(192, 192, 192);
|
||||
border-left: 1px solid var(--ButtonFace);
|
||||
border-right: 1px solid rgb(0, 0, 0);
|
||||
border-right: 1px solid var(--ButtonDkShadow);
|
||||
border-bottom: 1px solid rgb(0, 0, 0);
|
||||
border-bottom: 1px solid var(--ButtonDkShadow);
|
||||
box-shadow: 1px 1px 0 rgb(255, 255, 255) inset, -1px -1px 0 rgb(128, 128, 128) inset;
|
||||
box-shadow: 1px 1px 0 var(--ButtonHilight) inset, -1px -1px 0 var(--ButtonShadow) inset;
|
||||
}
|
||||
.scrollbar-track-piece:hover:active {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2P8/////4MHDzIwHjhw4L+9vT0DAHAFCj6esq3FAAAAAElFTkSuQmCC") repeat;
|
||||
background: var(--checker) repeat;
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
background-color: white;
|
||||
background-blend-mode: difference;
|
||||
/* background-attachment: fixed; breaks the checkered background in chrome */
|
||||
}
|
||||
.scrollbar-track-piece.increment {
|
||||
background-position: bottom;
|
||||
}
|
||||
.scrollbar-corner {
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
}
|
||||
|
||||
.scrollbar-button {
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
border-top: 1px solid rgb(192, 192, 192);
|
||||
border-top: 1px solid var(--ButtonFace);
|
||||
border-left: 1px solid rgb(192, 192, 192);
|
||||
border-left: 1px solid var(--ButtonFace);
|
||||
border-right: 1px solid rgb(0, 0, 0);
|
||||
border-right: 1px solid var(--ButtonDkShadow);
|
||||
border-bottom: 1px solid rgb(0, 0, 0);
|
||||
border-bottom: 1px solid var(--ButtonDkShadow);
|
||||
box-shadow: 1px 1px 0 rgb(255, 255, 255) inset, -1px -1px 0 rgb(128, 128, 128) inset;
|
||||
box-shadow: 1px 1px 0 var(--ButtonHilight) inset, -1px -1px 0 var(--ButtonShadow) inset;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAW0lEQVQ4T2NkGGSAcZC5h4FWDvrPwEC02ShqkR0EkkAHuBxMyEKYWYQ8jKEOXQOyo/A5BuZwqqvBZiA+3xMbilQLIWqlcUJRimwPzjRELcdQZA6hREeR4eRoBgBoXhAK6oiMhwAAAABJRU5ErkJggg==");
|
||||
background-image: var(--scrollbar-arrows-ButtonText);
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: pixelated;
|
||||
width: 13px;
|
||||
width: var(--scrollbar-size);
|
||||
height: 13px;
|
||||
height: var(--scrollbar-size);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.scrollbar-button:not(.disabled):hover:active {
|
||||
border: 1px solid rgb(128, 128, 128);
|
||||
border: 1px solid var(--ButtonShadow);
|
||||
box-shadow: none;
|
||||
}
|
||||
.scrollbar-button.disabled {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDmpoaPjf0NBAlNnoauGaQBLooYXLUEIWwswi5Chs6lB8gewofI6BOZwWajCCFZ/viQ1FqoUQtRI4oShFtgdnGqKWYyg1h6icQKklpOgHAM9mQArEvm5+AAAAAElFTkSuQmCC"), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDvr///9/RkZGosxGVwvXBJJADy1chhKyEGYWIUdhU4fiC2RH4XMMzOG0UIMRrPh8T2woUi2EqJXACUUpsj040xC1HEOpOUTlBEotIUU/AKXFQAqyTJ6DAAAAAElFTkSuQmCC");
|
||||
background-image: var(--scrollbar-arrows-GrayText), var(--scrollbar-arrows-ButtonHilight);
|
||||
}
|
||||
|
||||
.scrollbar-button.horizontal.decrement.disabled {
|
||||
background-position: /* left arrow */
|
||||
calc(9px * -3 + 1px) 1px,
|
||||
calc(9px * -3 + 2px) 2px;
|
||||
background-position: /* left arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -3 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -3 + 2px) 2px;
|
||||
}
|
||||
.scrollbar-button.horizontal.increment.disabled {
|
||||
background-position: /* right arrow */
|
||||
calc(9px * -2 + 1px) 1px,
|
||||
calc(9px * -2 + 2px) 2px;
|
||||
background-position: /* right arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -2 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -2 + 2px) 2px;
|
||||
}
|
||||
.scrollbar-button.vertical.decrement.disabled {
|
||||
background-position: /* up arrow */
|
||||
calc(9px * -1 + 1px) 1px,
|
||||
calc(9px * -1 + 2px) 2px;
|
||||
background-position: /* up arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -1 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -1 + 2px) 2px;
|
||||
}
|
||||
.scrollbar-button.vertical.increment.disabled {
|
||||
background-position: /* down arrow */
|
||||
calc(9px * -0 + 1px) 1px,
|
||||
calc(9px * -0 + 2px) 2px;
|
||||
background-position: /* down arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -0 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -0 + 2px) 2px;
|
||||
}
|
||||
|
||||
.scrollbar-button.horizontal.decrement {
|
||||
background-position: calc(9px * -3 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -3 + 1px) 1px; /* left */
|
||||
}
|
||||
.scrollbar-button.horizontal.increment {
|
||||
background-position: calc(9px * -2 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -2 + 1px) 1px; /* right */
|
||||
}
|
||||
.scrollbar-button.vertical.decrement {
|
||||
background-position: calc(9px * -1 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -1 + 1px) 1px; /* up */
|
||||
}
|
||||
.scrollbar-button.vertical.increment {
|
||||
background-position: calc(9px * -0 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -0 + 1px) 1px; /* down */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar,
|
||||
::-webkit-scrollbar-thumb,
|
||||
::-webkit-scrollbar-button {
|
||||
width: 13px;
|
||||
width: var(--scrollbar-size);
|
||||
height: 13px;
|
||||
height: var(--scrollbar-size);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2P8/////4MHDzIwHjhw4L+9vT0DAHAFCj6esq3FAAAAAElFTkSuQmCC") repeat;
|
||||
background: var(--checker) repeat;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
border-top: 1px solid rgb(192, 192, 192);
|
||||
border-top: 1px solid var(--ButtonFace);
|
||||
border-left: 1px solid rgb(192, 192, 192);
|
||||
border-left: 1px solid var(--ButtonFace);
|
||||
border-right: 1px solid rgb(0, 0, 0);
|
||||
border-right: 1px solid var(--ButtonDkShadow);
|
||||
border-bottom: 1px solid rgb(0, 0, 0);
|
||||
border-bottom: 1px solid var(--ButtonDkShadow);
|
||||
box-shadow: 1px 1px 0 rgb(255, 255, 255) inset, -1px -1px 0 rgb(128, 128, 128) inset;
|
||||
box-shadow: 1px 1px 0 var(--ButtonHilight) inset, -1px -1px 0 var(--ButtonShadow) inset;
|
||||
}
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button {
|
||||
background-color: rgb(192, 192, 192);
|
||||
background-color: var(--ButtonFace);
|
||||
border-top: 1px solid rgb(192, 192, 192);
|
||||
border-top: 1px solid var(--ButtonFace);
|
||||
border-left: 1px solid rgb(192, 192, 192);
|
||||
border-left: 1px solid var(--ButtonFace);
|
||||
border-right: 1px solid rgb(0, 0, 0);
|
||||
border-right: 1px solid var(--ButtonDkShadow);
|
||||
border-bottom: 1px solid rgb(0, 0, 0);
|
||||
border-bottom: 1px solid var(--ButtonDkShadow);
|
||||
box-shadow: 1px 1px 0 rgb(255, 255, 255) inset, -1px -1px 0 rgb(128, 128, 128) inset;
|
||||
box-shadow: 1px 1px 0 var(--ButtonHilight) inset, -1px -1px 0 var(--ButtonShadow) inset;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAW0lEQVQ4T2NkGGSAcZC5h4FWDvrPwEC02ShqkR0EkkAHuBxMyEKYWYQ8jKEOXQOyo/A5BuZwqqvBZiA+3xMbilQLIWqlcUJRimwPzjRELcdQZA6hREeR4eRoBgBoXhAK6oiMhwAAAABJRU5ErkJggg==");
|
||||
background-image: var(--scrollbar-arrows-ButtonText);
|
||||
image-rendering: pixelated;
|
||||
width: 13px;
|
||||
width: var(--scrollbar-size);
|
||||
height: 13px;
|
||||
height: var(--scrollbar-size);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:not(.disabled):hover:active {
|
||||
border: 1px solid rgb(128, 128, 128);
|
||||
border: 1px solid var(--ButtonShadow);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.disabled {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDmpoaPjf0NBAlNnoauGaQBLooYXLUEIWwswi5Chs6lB8gewofI6BOZwWajCCFZ/viQ1FqoUQtRI4oShFtgdnGqKWYyg1h6icQKklpOgHAM9mQArEvm5+AAAAAElFTkSuQmCC"), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDvr///9/RkZGosxGVwvXBJJADy1chhKyEGYWIUdhU4fiC2RH4XMMzOG0UIMRrPh8T2woUi2EqJXACUUpsj040xC1HEOpOUTlBEotIUU/AKXFQAqyTJ6DAAAAAElFTkSuQmCC");
|
||||
background-image: var(--scrollbar-arrows-GrayText), var(--scrollbar-arrows-ButtonHilight);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.horizontal.decrement.disabled {
|
||||
background-position: /* left arrow */
|
||||
calc(9px * -3 + 1px) 1px,
|
||||
calc(9px * -3 + 2px) 2px;
|
||||
background-position: /* left arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -3 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -3 + 2px) 2px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.horizontal.increment.disabled {
|
||||
background-position: /* right arrow */
|
||||
calc(9px * -2 + 1px) 1px,
|
||||
calc(9px * -2 + 2px) 2px;
|
||||
background-position: /* right arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -2 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -2 + 2px) 2px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.vertical.decrement.disabled {
|
||||
background-position: /* up arrow */
|
||||
calc(9px * -1 + 1px) 1px,
|
||||
calc(9px * -1 + 2px) 2px;
|
||||
background-position: /* up arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -1 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -1 + 2px) 2px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.vertical.increment.disabled {
|
||||
background-position: /* down arrow */
|
||||
calc(9px * -0 + 1px) 1px,
|
||||
calc(9px * -0 + 2px) 2px;
|
||||
background-position: /* down arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -0 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -0 + 2px) 2px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.horizontal.decrement {
|
||||
background-position: calc(9px * -3 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -3 + 1px) 1px;
|
||||
/* left */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.horizontal.increment {
|
||||
background-position: calc(9px * -2 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -2 + 1px) 1px;
|
||||
/* right */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.vertical.decrement {
|
||||
background-position: calc(9px * -1 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -1 + 1px) 1px;
|
||||
/* up */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button.vertical.increment {
|
||||
background-position: calc(9px * -0 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -0 + 1px) 1px;
|
||||
/* down */
|
||||
}
|
||||
::-webkit-scrollbar-button:hover:active {
|
||||
border: 1px solid rgb(128, 128, 128);
|
||||
border: 1px solid var(--ButtonShadow);
|
||||
box-shadow: none;
|
||||
}
|
||||
::-webkit-scrollbar-button:disabled {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDmpoaPjf0NBAlNnoauGaQBLooYXLUEIWwswi5Chs6lB8gewofI6BOZwWajCCFZ/viQ1FqoUQtRI4oShFtgdnGqKWYyg1h6icQKklpOgHAM9mQArEvm5+AAAAAElFTkSuQmCC"), url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDvr///9/RkZGosxGVwvXBJJADy1chhKyEGYWIUdhU4fiC2RH4XMMzOG0UIMRrPh8T2woUi2EqJXACUUpsj040xC1HEOpOUTlBEotIUU/AKXFQAqyTJ6DAAAAAElFTkSuQmCC");
|
||||
background-image: var(--scrollbar-arrows-GrayText), var(--scrollbar-arrows-ButtonHilight);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:horizontal:decrement:disabled {
|
||||
background-position: /* left arrow */
|
||||
calc(9px * -3 + 1px) 1px,
|
||||
calc(9px * -3 + 2px) 2px;
|
||||
background-position: /* left arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -3 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -3 + 2px) 2px;
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:increment:disabled {
|
||||
background-position: /* right arrow */
|
||||
calc(9px * -2 + 1px) 1px,
|
||||
calc(9px * -2 + 2px) 2px;
|
||||
background-position: /* right arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -2 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -2 + 2px) 2px;
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:decrement:disabled {
|
||||
background-position: /* up arrow */
|
||||
calc(9px * -1 + 1px) 1px,
|
||||
calc(9px * -1 + 2px) 2px;
|
||||
background-position: /* up arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -1 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -1 + 2px) 2px;
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:increment:disabled {
|
||||
background-position: /* down arrow */
|
||||
calc(9px * -0 + 1px) 1px,
|
||||
calc(9px * -0 + 2px) 2px;
|
||||
background-position: /* down arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -0 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -0 + 2px) 2px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:horizontal:decrement.disabled {
|
||||
background-position: /* left arrow */
|
||||
calc(9px * -3 + 1px) 1px,
|
||||
calc(9px * -3 + 2px) 2px;
|
||||
background-position: /* left arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -3 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -3 + 2px) 2px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button:horizontal:decrement {
|
||||
background-position: calc(9px * -3 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -3 + 1px) 1px;
|
||||
/* left */
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:increment.disabled {
|
||||
background-position: /* right arrow */
|
||||
calc(9px * -2 + 1px) 1px,
|
||||
calc(9px * -2 + 2px) 2px;
|
||||
background-position: /* right arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -2 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -2 + 2px) 2px;
|
||||
}
|
||||
::-webkit-scrollbar-button:horizontal:increment {
|
||||
background-position: calc(9px * -2 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -2 + 1px) 1px;
|
||||
/* right */
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:decrement.disabled {
|
||||
background-position: /* up arrow */
|
||||
calc(9px * -1 + 1px) 1px,
|
||||
calc(9px * -1 + 2px) 2px;
|
||||
background-position: /* up arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -1 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -1 + 2px) 2px;
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:decrement {
|
||||
background-position: calc(9px * -1 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -1 + 1px) 1px;
|
||||
/* up */
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:increment.disabled {
|
||||
background-position: /* down arrow */
|
||||
calc(9px * -0 + 1px) 1px,
|
||||
calc(9px * -0 + 2px) 2px;
|
||||
background-position: /* down arrow */
|
||||
calc(var(--scrollbar-button-inner-size) * -0 + 1px) 1px,
|
||||
calc(var(--scrollbar-button-inner-size) * -0 + 2px) 2px;
|
||||
}
|
||||
::-webkit-scrollbar-button:vertical:increment {
|
||||
background-position: calc(9px * -0 + 1px) 1px;
|
||||
background-position: calc(var(--scrollbar-button-inner-size) * -0 + 1px) 1px;
|
||||
/* down */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track-piece:hover:active {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2P8/////4MHDzIwHjhw4L+9vT0DAHAFCj6esq3FAAAAAElFTkSuQmCC") repeat;
|
||||
background: var(--checker) repeat;
|
||||
image-rendering: pixelated;
|
||||
background-color: white;
|
||||
background-blend-mode: difference;
|
||||
/* background-attachment: fixed; breaks the checkered background in chrome */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track-piece.increment {
|
||||
background-position: bottom;
|
||||
}
|
||||
::-webkit-scrollbar-track-piece:increment {
|
||||
background-position: bottom;
|
||||
}
|
||||
|
||||
/* turn off double buttons */
|
||||
::-webkit-scrollbar-button:start:increment,
|
||||
::-webkit-scrollbar-button:end:decrement {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=windows-98.css.map */
|
||||
1
static/html/jspaint/lib/os-gui/windows-98.css.map
Normal file
1
static/html/jspaint/lib/os-gui/windows-98.css.map
Normal file
File diff suppressed because one or more lines are too long
48
static/html/jspaint/lib/os-gui/windows-default.css
Normal file
48
static/html/jspaint/lib/os-gui/windows-default.css
Normal file
@@ -0,0 +1,48 @@
|
||||
:root {
|
||||
/* These resources are generated. */
|
||||
/* JS: makeThemeCSSFile(renderThemeGraphics(getComputedStyle(document.documentElement))) */
|
||||
--checker: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAG0lEQVQYV2P8/////4MHDzIwHjhw4L+9vT0DAHAFCj6esq3FAAAAAElFTkSuQmCC");
|
||||
--button-active-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--button-normal-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--inset-deep-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h224v32h-192v192h-32v-224z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M224%200h32v256h-256v-32h224v-224z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M192%2032h32v192h-192v-32h160v-160z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--button-default-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h160v32h-128v128h-32v-160z%22%20fill%3D%22%20rgb(255%2C%20255%2C%20255)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h96v32h-64v64h-32v-96z%22%20fill%3D%22%20rgb(223%2C%20223%2C%20223)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M160%2064h32v128h-128v-32h96v-96z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M96%2096h64v64h-64v-64z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22%20rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 96 / 3px;
|
||||
--button-default-active-border-image: url("data:image/svg+xml,%3Csvg%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22256px%22%20height%3D%22256px%22%20viewBox%3D%220%200%20256%20256%22%3E%0A%09%09%09%0A%09%09%3Cpath%20d%3D%22M0%200h256v256h-256v-256z%22%20fill%3D%22%20rgb(0%2C%200%2C%200)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M32%2032h192v192h-192v-192z%22%20fill%3D%22%20rgb(128%2C%20128%2C%20128)%22%2F%3E%0A%09%09%3Cpath%20d%3D%22M64%2064h128v128h-128v-128z%22%20fill%3D%22%20rgb(192%2C%20192%2C%20192)%22%2F%3E%0A%09%09%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%22256%22%20height%3D%22256%22%20stroke-width%3D%2264%22%20stroke%3D%22%20rgb(0%2C%200%2C%200)%22%20fill%3D%22none%22%2F%3E%0A%09%0A%09%09%3C%2Fsvg%3E") 64 / 2px;
|
||||
--scrollbar-arrows-ButtonText: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAW0lEQVQ4T2NkGGSAcZC5h4FWDvrPwEC02ShqkR0EkkAHuBxMyEKYWYQ8jKEOXQOyo/A5BuZwqqvBZiA+3xMbilQLIWqlcUJRimwPzjRELcdQZA6hREeR4eRoBgBoXhAK6oiMhwAAAABJRU5ErkJggg==");
|
||||
--scrollbar-arrows-GrayText: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDmpoaPjf0NBAlNnoauGaQBLooYXLUEIWwswi5Chs6lB8gewofI6BOZwWajCCFZ/viQ1FqoUQtRI4oShFtgdnGqKWYyg1h6icQKklpOgHAM9mQArEvm5+AAAAAElFTkSuQmCC");
|
||||
--scrollbar-arrows-ButtonHilight: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAAYElEQVQ4T2NkGGSAcZC5h4EmDvr///9/RkZGosxGVwvXBJJADy1chhKyEGYWIUdhU4fiC2RH4XMMzOG0UIMRrPh8T2woUi2EqJXACUUpsj040xC1HEOpOUTlBEotIUU/AKXFQAqyTJ6DAAAAAElFTkSuQmCC");
|
||||
--scrollbar-size: 13px;
|
||||
--scrollbar-button-inner-size: 9px;
|
||||
|
||||
/* Colors */
|
||||
--ActiveBorder: rgb(192, 192, 192);
|
||||
--ActiveTitle: rgb(0, 0, 128);
|
||||
--AppWorkspace: rgb(128, 128, 128);
|
||||
--Background: rgb(0, 128, 128);
|
||||
--ButtonAlternateFace: rgb(180, 180, 180);
|
||||
--ButtonDkShadow: rgb(0, 0, 0);
|
||||
--ButtonFace: rgb(192, 192, 192);
|
||||
--ButtonHilight: rgb(255, 255, 255);
|
||||
--ButtonLight: rgb(223, 223, 223);
|
||||
--ButtonShadow: rgb(128, 128, 128);
|
||||
--ButtonText: rgb(0, 0, 0);
|
||||
--GradientActiveTitle: rgb(16, 132, 208);
|
||||
--GradientInactiveTitle: rgb(181, 181, 181);
|
||||
--GrayText: rgb(128, 128, 128);
|
||||
--Hilight: rgb(0, 0, 128);
|
||||
--HilightText: rgb(255, 255, 255);
|
||||
--HotTrackingColor: rgb(0, 0, 255);
|
||||
--InactiveBorder: rgb(192, 192, 192);
|
||||
--InactiveTitle: rgb(128, 128, 128);
|
||||
--InactiveTitleText: rgb(192, 192, 192);
|
||||
--InfoText: rgb(0, 0, 0);
|
||||
--InfoWindow: rgb(255, 255, 225);
|
||||
--Menu: rgb(192, 192, 192);
|
||||
--MenuText: rgb(0, 0, 0);
|
||||
--Scrollbar: rgb(192, 192, 192);
|
||||
--TitleText: rgb(255, 255, 255);
|
||||
--Window: rgb(255, 255, 255);
|
||||
--WindowFrame: rgb(0, 0, 0);
|
||||
--WindowText: rgb(0, 0, 0);
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=windows-default.css.map */
|
||||
1
static/html/jspaint/lib/os-gui/windows-default.css.map
Normal file
1
static/html/jspaint/lib/os-gui/windows-default.css.map
Normal file
File diff suppressed because one or more lines are too long
1
static/html/jspaint/lib/pako-2.0.3.min.js
vendored
Normal file
1
static/html/jspaint/lib/pako-2.0.3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
177
static/html/jspaint/lib/pdf.js/LICENSE
Normal file
177
static/html/jspaint/lib/pdf.js/LICENSE
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
14827
static/html/jspaint/lib/pdf.js/build/pdf.js
Normal file
14827
static/html/jspaint/lib/pdf.js/build/pdf.js
Normal file
File diff suppressed because it is too large
Load Diff
1
static/html/jspaint/lib/pdf.js/build/pdf.js.map
Normal file
1
static/html/jspaint/lib/pdf.js/build/pdf.js.map
Normal file
File diff suppressed because one or more lines are too long
313
static/html/jspaint/lib/pdf.js/build/pdf.sandbox.js
Normal file
313
static/html/jspaint/lib/pdf.js/build/pdf.sandbox.js
Normal file
File diff suppressed because one or more lines are too long
1
static/html/jspaint/lib/pdf.js/build/pdf.sandbox.js.map
Normal file
1
static/html/jspaint/lib/pdf.js/build/pdf.sandbox.js.map
Normal file
File diff suppressed because one or more lines are too long
65293
static/html/jspaint/lib/pdf.js/build/pdf.worker.js
vendored
Normal file
65293
static/html/jspaint/lib/pdf.js/build/pdf.worker.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
static/html/jspaint/lib/pdf.js/build/pdf.worker.js.map
vendored
Normal file
1
static/html/jspaint/lib/pdf.js/build/pdf.worker.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-EUC-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-EUC-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-EUC-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-EUC-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-RKSJ-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-RKSJ-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78ms-RKSJ-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78ms-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78ms-RKSJ-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/78ms-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/83pv-RKSJ-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/83pv-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90ms-RKSJ-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90ms-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90ms-RKSJ-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90ms-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90msp-RKSJ-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90msp-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90msp-RKSJ-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90msp-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90pv-RKSJ-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90pv-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90pv-RKSJ-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/90pv-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Add-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Add-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Add-RKSJ-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Add-RKSJ-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Add-RKSJ-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Add-RKSJ-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Add-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Add-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-0.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-0.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-1.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-1.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-2.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-2.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-3.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-3.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-4.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-4.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-5.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-5.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-6.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-6.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-UCS2.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-CNS1-UCS2.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-0.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-0.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-1.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-1.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-2.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-2.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-3.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-3.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-4.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-4.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-5.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-5.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-UCS2.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-GB1-UCS2.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-0.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-0.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-1.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-1.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-2.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-2.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-3.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-3.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-4.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-4.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-5.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-5.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-6.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-6.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-UCS2.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Japan1-UCS2.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Korea1-0.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Korea1-0.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Korea1-1.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Korea1-1.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Korea1-2.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Korea1-2.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Korea1-UCS2.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/Adobe-Korea1-UCS2.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/B5-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/B5-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/B5-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/B5-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/B5pc-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/B5pc-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/B5pc-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/B5pc-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS-EUC-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS-EUC-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS-EUC-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS-EUC-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS1-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS1-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS1-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS1-V.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS2-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/CNS2-H.bcmap
Normal file
Binary file not shown.
3
static/html/jspaint/lib/pdf.js/web/cmaps/CNS2-V.bcmap
Normal file
3
static/html/jspaint/lib/pdf.js/web/cmaps/CNS2-V.bcmap
Normal file
@@ -0,0 +1,3 @@
|
||||
<03>RCopyright 1990-2009 Adobe Systems Incorporated.
|
||||
All rights reserved.
|
||||
See ./LICENSE<53>CNS2-H
|
||||
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/ETHK-B5-H.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/ETHK-B5-H.bcmap
Normal file
Binary file not shown.
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/ETHK-B5-V.bcmap
Normal file
BIN
static/html/jspaint/lib/pdf.js/web/cmaps/ETHK-B5-V.bcmap
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user