update lang and components

* only EN lang ATM
* separate component and builder page
*add flatpickr input
* add select validation
* start svg on buttons
This commit is contained in:
Jordan Blasenhauer 2024-05-17 16:04:56 +02:00
parent f352f7ac51
commit 65403966b4
23 changed files with 2658 additions and 432 deletions

View file

@ -231,6 +231,18 @@ body {
@apply border-gray-50/0 ring-1 ring-green-500;
}
.invalid.select-btn,
.invalid.select-btn:hover,
.invalid.select-btn:focus,
.invalid.select-btn:active {
@apply border-gray-50/0 ring-1 ring-red-500;
}
.valid.select-btn:focus,
.valid.select-btn:active {
@apply border-gray-50/0 ring-1 ring-green-500;
}
.invalid.checkbox,
.invalid.checkbox:hover,
.invalid.checkbox:focus,
@ -247,6 +259,10 @@ body {
.invalid.input-regular:disabled:hover,
.invalid.input-regular:disabled:focus,
.invalid.input-regular:disabled:active,
.invalid.select-btn:disabled,
.invalid.select-btn:disabled:hover,
.invalid.select-btn:disabled:focus,
.invalid.select-btn:disabled:active,
.invalid.checkbox:disabled,
.invalid.checkbox:disabled:hover,
.invalid.checkbox:disabled:focus,
@ -255,6 +271,10 @@ body {
.valid.input-regular:disabled:hover,
.valid.input-regular:disabled:focus,
.valid.input-regular:disabled:active,
.valid.select-btn:disabled,
.valid.select-btn:disabled:hover,
.valid.select-btn:disabled:focus,
.valid.select-btn:disabled:active,
.valid.checkbox:disabled,
.valid.checkbox:disabled:hover,
.valid.checkbox:disabled:focus,

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,3 @@
.datepicker{display:none}.datepicker.active{display:block}.datepicker-dropdown{position:absolute;top:0;left:0;z-index:100;padding-top:4px}.datepicker-dropdown.datepicker-orient-top{padding-top:0;padding-bottom:4px}.datepicker-picker{display:inline-block;border-radius:0;background-color:#fefefe}.datepicker-dropdown .datepicker-picker{box-shadow:0 0 0 1px #cacaca}.datepicker-picker span{display:block;flex:1;border:0;border-radius:0;cursor:default;text-align:center;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.datepicker-main{padding:2px}.datepicker-footer{box-shadow:inset 0 1px 1px rgba(10,10,10,.1);background-color:#e6e6e6}.datepicker-controls,.datepicker-grid,.datepicker-view,.datepicker-view .days-of-week{display:flex}.datepicker-grid{flex-wrap:wrap;width:15.75rem}.datepicker-view .days .datepicker-cell,.datepicker-view .dow{flex-basis:14.2857142857%}.datepicker-view.datepicker-grid .datepicker-cell{flex-basis:25%;height:4.5rem;line-height:4.5rem}.datepicker-cell,.datepicker-view .week{height:2.25rem;line-height:2.25rem}.datepicker-title{box-shadow:inset 0 -1px 1px rgba(10,10,10,.1);background-color:#e6e6e6;padding:.375rem .75rem;text-align:center;font-weight:700}.datepicker-header .datepicker-controls{padding:2px 2px 0}.datepicker-controls .button{margin:.4rem 0;background-color:#fefefe;color:#707070}.datepicker-controls .button:focus,.datepicker-controls .button:hover{background-color:#d8d8d8}.datepicker-controls .button:focus[disabled],.datepicker-controls .button:hover[disabled]{opacity:.25;background-color:#fefefe;margin-top:.4rem;margin-bottom:.4rem;color:#707070}.datepicker-header .datepicker-controls .button{border-color:transparent;font-weight:700}.datepicker-footer .datepicker-controls .button{margin:calc(.375rem - 1px) .375rem;border-radius:0;width:100%;font-size:.75rem}.datepicker-controls .view-switch{flex:auto}.datepicker-controls .next-btn,.datepicker-controls .prev-btn{padding-right:.375rem;padding-left:.375rem;width:2.25rem}.datepicker-controls .next-btn.disabled,.datepicker-controls .prev-btn.disabled{visibility:hidden}.datepicker-view .dow{height:1.5rem;line-height:1.5rem;font-size:.875rem;font-weight:700;color:#064059}.datepicker-view .week{width:2.25rem;color:#8a8a8a;font-size:.75rem}@media (max-width:22.5rem){.datepicker-view .week{width:1.96875rem}.calendar-weeks+.days .datepicker-grid{width:13.78125rem}}.datepicker-cell:not(.disabled):hover{background-color:#f8f8f8;cursor:pointer}.datepicker-cell.focused:not(.selected),.datepicker-cell.highlighted:not(.selected):not(.range):not(.today).focused,.datepicker-cell.highlighted:not(.selected):not(.range):not(.today):not(
.disabled
):hover{background-color:#f1f1f1}.datepicker-cell.selected,.datepicker-cell.selected:hover{background-color:#1779ba;color:#fefefe;font-weight:semibold}.datepicker-cell.disabled{color:#e6e6e6}.datepicker-cell.next:not(.disabled),.datepicker-cell.prev:not(.disabled){color:#cacaca}.datepicker-cell.next.selected,.datepicker-cell.prev.selected{color:#e5e5e5}.datepicker-cell.highlighted:not(.selected):not(.range):not(.today){border-radius:0;background-color:#f7f7f7}.datepicker-cell.today:not(.selected){background-color:#d7ecfa}.datepicker-cell.today:not(.selected):not(.disabled){color:#8a8a8a}.datepicker-cell.today.focused:not(.selected){background-color:#cbe7f9}.datepicker-cell.range-end:not(.selected),.datepicker-cell.range-start:not(.selected){background-color:#767676;color:#fefefe}.datepicker-cell.range-end.focused:not(.selected),.datepicker-cell.range-start.focused:not(.selected){background-color:#707070}.datepicker-cell.range-end,.datepicker-cell.range-start{border-radius:0}.datepicker-cell.range{border-radius:0;background-color:#e6e6e6}.datepicker-cell.range:not(.disabled):not(.focused):not(.today):hover{background-color:#e0e0e0}.datepicker-cell.range.disabled{color:#cdcdcd}.datepicker-cell.range.focused{background-color:#d9d9d9}.datepicker-cell.range.today{background-color:#b3dbf6}.datepicker-input.in-edit{border-color:#a4a4a4}.datepicker-input.in-edit:active,.datepicker-input.in-edit:focus{box-shadow:0 0 .25em .25em rgba(164,164,164,.2)}

View file

@ -0,0 +1,833 @@
.flatpickr-calendar {
background: transparent;
opacity: 0;
display: none;
text-align: center;
visibility: hidden;
padding: 0;
-webkit-animation: none;
animation: none;
direction: ltr;
border: 0;
font-size: 14px;
line-height: 24px;
border-radius: 5px;
position: absolute;
width: 307.875px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-touch-action: manipulation;
touch-action: manipulation;
-webkit-box-shadow: 0 3px 13px rgba(0, 0, 0, 0.08);
box-shadow: 0 3px 13px rgba(0, 0, 0, 0.08);
}
.flatpickr-calendar.open,
.flatpickr-calendar.inline {
opacity: 1;
max-height: 640px;
visibility: visible;
}
.flatpickr-calendar.open {
display: inline-block;
z-index: 99999;
}
.flatpickr-calendar.animate.open {
-webkit-animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.flatpickr-calendar.inline {
display: block;
position: relative;
top: 2px;
}
.flatpickr-calendar.static {
position: absolute;
top: calc(100% + 2px);
}
.flatpickr-calendar.static.open {
z-index: 999;
display: block;
}
.flatpickr-calendar.multiMonth
.flatpickr-days
.dayContainer:nth-child(n + 1)
.flatpickr-day.inRange:nth-child(7n + 7) {
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.flatpickr-calendar.multiMonth
.flatpickr-days
.dayContainer:nth-child(n + 2)
.flatpickr-day.inRange:nth-child(7n + 1) {
-webkit-box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
}
.flatpickr-calendar .hasWeeks .dayContainer,
.flatpickr-calendar .hasTime .dayContainer {
border-bottom: 0;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.flatpickr-calendar .hasWeeks .dayContainer {
border-left: 0;
}
.flatpickr-calendar.hasTime .flatpickr-time {
height: 40px;
border-top: 1px solid rgba(72, 72, 72, 0.2);
}
.flatpickr-calendar.hasTime .flatpickr-innerContainer {
border-bottom: 0;
}
.flatpickr-calendar.hasTime .flatpickr-time {
border: 1px solid rgba(72, 72, 72, 0.2);
}
.flatpickr-calendar.noCalendar.hasTime .flatpickr-time {
height: auto;
}
.flatpickr-calendar:before,
.flatpickr-calendar:after {
position: absolute;
display: block;
pointer-events: none;
border: solid transparent;
content: "";
height: 0;
width: 0;
left: 22px;
}
.flatpickr-calendar.rightMost:before,
.flatpickr-calendar.arrowRight:before,
.flatpickr-calendar.rightMost:after,
.flatpickr-calendar.arrowRight:after {
left: auto;
right: 22px;
}
.flatpickr-calendar.arrowCenter:before,
.flatpickr-calendar.arrowCenter:after {
left: 50%;
right: 50%;
}
.flatpickr-calendar:before {
border-width: 5px;
margin: 0 -5px;
}
.flatpickr-calendar:after {
border-width: 4px;
margin: 0 -4px;
}
.flatpickr-calendar.arrowTop:before,
.flatpickr-calendar.arrowTop:after {
bottom: 100%;
}
.flatpickr-calendar.arrowTop:before {
border-bottom-color: rgba(72, 72, 72, 0.2);
}
.flatpickr-calendar.arrowTop:after {
border-bottom-color: #085577;
}
.flatpickr-calendar.arrowBottom:before,
.flatpickr-calendar.arrowBottom:after {
top: 100%;
}
.flatpickr-calendar.arrowBottom:before {
border-top-color: rgba(72, 72, 72, 0.2);
}
.flatpickr-calendar.arrowBottom:after {
border-top-color: #085577;
}
.flatpickr-calendar:focus {
outline: 0;
}
.flatpickr-wrapper {
position: relative;
display: inline-block;
}
.flatpickr-months {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.flatpickr-months .flatpickr-month {
border-radius: 5px 5px 0 0;
background: #085577;
color: #fff;
fill: #fff;
height: 34px;
line-height: 1;
text-align: center;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.flatpickr-months .flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-decoration: none;
cursor: pointer;
position: absolute;
top: -3px;
height: 34px;
padding: 10px;
z-index: 3;
color: #fff;
fill: #fff;
}
.flatpickr-months .flatpickr-prev-month.flatpickr-disabled,
.flatpickr-months .flatpickr-next-month.flatpickr-disabled {
display: none;
}
.flatpickr-months .flatpickr-prev-month i,
.flatpickr-months .flatpickr-next-month i {
position: relative;
}
.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,
.flatpickr-months .flatpickr-next-month.flatpickr-prev-month {
/*
/*rtl:begin:ignore*/
/*
*/
left: 0;
/*
/*rtl:end:ignore*/
/*
*/
}
/*
/*rtl:begin:ignore*/
/*
/*rtl:end:ignore*/
.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,
.flatpickr-months .flatpickr-next-month.flatpickr-next-month {
/*
/*rtl:begin:ignore*/
/*
*/
right: 0;
/*
/*rtl:end:ignore*/
/*
*/
}
/*
/*rtl:begin:ignore*/
/*
/*rtl:end:ignore*/
.flatpickr-months .flatpickr-prev-month:hover,
.flatpickr-months .flatpickr-next-month:hover {
color: #bbb;
}
.flatpickr-months .flatpickr-prev-month:hover svg,
.flatpickr-months .flatpickr-next-month:hover svg {
fill: #40bb6b;
}
.flatpickr-months .flatpickr-prev-month svg,
.flatpickr-months .flatpickr-next-month svg {
width: 14px;
height: 14px;
}
.flatpickr-months .flatpickr-prev-month svg path,
.flatpickr-months .flatpickr-next-month svg path {
-webkit-transition: fill 0.1s;
transition: fill 0.1s;
fill: inherit;
}
.numInputWrapper {
position: relative;
height: auto;
margin-left: 12px;
}
.numInputWrapper input,
.numInputWrapper span {
display: inline-block;
}
.numInputWrapper input {
width: 100%;
}
.numInputWrapper input::-ms-clear {
display: none;
}
.numInputWrapper input::-webkit-outer-spin-button,
.numInputWrapper input::-webkit-inner-spin-button {
margin: 0;
-webkit-appearance: none;
}
.numInputWrapper span {
position: absolute;
right: 0;
width: 14px;
padding: 0 4px 0 2px;
height: 50%;
line-height: 50%;
opacity: 0;
cursor: pointer;
border-right: 1px solid rgba(72, 72, 72, 0.15);
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.numInputWrapper span:hover {
background: rgba(0, 0, 0, 0.1);
}
.numInputWrapper span:active {
background: rgba(0, 0, 0, 0.2);
}
.numInputWrapper span:after {
display: block;
content: "";
position: absolute;
}
.numInputWrapper span.arrowUp {
top: 0;
border-bottom: 0;
}
.numInputWrapper span.arrowUp:after {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 4px solid rgba(72, 72, 72, 0.6);
top: 26%;
}
.numInputWrapper span.arrowDown {
top: 50%;
}
.numInputWrapper span.arrowDown:after {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid rgba(72, 72, 72, 0.6);
top: 40%;
}
.numInputWrapper span svg {
width: inherit;
height: auto;
}
.numInputWrapper span svg path {
fill: rgba(255, 255, 255, 0.5);
}
.numInputWrapper:hover {
background: rgba(0, 0, 0, 0.05);
}
.numInputWrapper span {
opacity: 1;
}
.flatpickr-current-month {
z-index: 1000;
font-size: 16px;
line-height: inherit;
font-weight: 300;
color: inherit;
position: absolute;
width: 75%;
left: 12.5%;
padding: 7.48px 0 0 0;
line-height: 1;
height: 34px;
display: inline-block;
text-align: center;
-webkit-transform: translate3d(0px, 0px, 0px);
transform: translate3d(0px, 0px, 0px);
}
.flatpickr-current-month span.cur-month {
font-family: inherit;
font-weight: 700;
color: inherit;
display: inline-block;
margin-left: 0.5ch;
padding: 0;
}
.flatpickr-current-month span.cur-month:hover {
background: rgba(0, 0, 0, 0.05);
}
.flatpickr-current-month .numInputWrapper {
width: 6ch;
width: 7ch\0;
display: inline-block;
}
.flatpickr-current-month .numInputWrapper span.arrowUp:after {
border-bottom-color: #fff;
}
.flatpickr-current-month .numInputWrapper span.arrowDown:after {
border-top-color: #fff;
}
.flatpickr-current-month input.cur-year {
background: transparent;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: inherit;
cursor: text;
margin: 0;
padding-right: 4px;
display: inline-block;
font-size: inherit;
font-family: inherit;
font-weight: 300;
line-height: inherit;
height: auto;
border: 0;
border-radius: 0;
vertical-align: initial;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
.flatpickr-current-month input.cur-year:focus {
outline: 0;
}
.flatpickr-current-month input.cur-year[disabled],
.flatpickr-current-month input.cur-year[disabled]:hover {
font-size: 100%;
color: rgba(255, 255, 255, 0.5);
background: transparent;
pointer-events: none;
}
.flatpickr-current-month .flatpickr-monthDropdown-months {
appearance: menulist;
background: #085577;
border: none;
border-radius: 0;
box-sizing: border-box;
color: inherit;
cursor: pointer;
font-size: inherit;
font-family: inherit;
font-weight: 300;
height: auto;
line-height: inherit;
margin: -1px 0 0 0;
outline: none;
padding: 0 0 0 0.5ch;
position: relative;
vertical-align: initial;
-webkit-box-sizing: border-box;
-webkit-appearance: menulist;
-moz-appearance: menulist;
width: auto;
}
.flatpickr-current-month .flatpickr-monthDropdown-months:focus,
.flatpickr-current-month .flatpickr-monthDropdown-months:active {
outline: none;
}
.flatpickr-current-month .flatpickr-monthDropdown-months:hover {
background: rgba(0, 0, 0, 0.05);
}
.flatpickr-current-month
.flatpickr-monthDropdown-months
.flatpickr-monthDropdown-month {
background-color: #085577;
border-color: #085577;
outline: none;
padding: 0;
border-radius: 4px ;
appearance: none;
}
.flatpickr-weekdays {
background: #085577;
text-align: center;
overflow: hidden;
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
height: 28px;
}
.flatpickr-weekdays .flatpickr-weekdaycontainer {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
span.flatpickr-weekday {
cursor: default;
font-size: 90%;
background: #085577;
color: white;
line-height: 1;
margin: 0;
text-align: center;
display: block;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
font-weight: bolder;
}
.dayContainer,
.flatpickr-weeks {
padding: 1px 0 0 0;
}
.flatpickr-days {
position: relative;
overflow: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align: start;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start;
width: 307.875px;
border-left: 1px solid rgba(72, 72, 72, 0.2);
border-right: 1px solid rgba(72, 72, 72, 0.2);
}
.flatpickr-days:focus {
outline: 0;
}
.dayContainer {
padding: 4px;
outline: 0;
text-align: left;
width: 307.875px;
min-width: 307.875px;
max-width: 307.875px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: inline-block;
display: -ms-flexbox;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-wrap: wrap;
-ms-flex-pack: justify;
-webkit-justify-content: space-around;
justify-content: space-around;
-webkit-transform: translate3d(0px, 0px, 0px);
transform: translate3d(0px, 0px, 0px);
opacity: 1;
}
.dayContainer + .dayContainer {
-webkit-box-shadow: -1px 0 0 rgba(72, 72, 72, 0.2);
box-shadow: -1px 0 0 rgba(72, 72, 72, 0.2);
}
.flatpickr-day {
background: none;
border: 1px solid transparent;
border-radius: 150px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: #484848;
cursor: pointer;
font-weight: 400;
width: 14.2857143%;
-webkit-flex-basis: 14.2857143%;
-ms-flex-preferred-size: 14.2857143%;
flex-basis: 14.2857143%;
max-width: 39px;
height: 39px;
line-height: 39px;
margin: 1.5px;
display: inline-block;
position: relative;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
text-align: center;
}
.flatpickr-day.inRange,
.flatpickr-day.prevMonthDay.inRange,
.flatpickr-day.nextMonthDay.inRange,
.flatpickr-day.today.inRange,
.flatpickr-day.prevMonthDay.today.inRange,
.flatpickr-day.nextMonthDay.today.inRange,
.flatpickr-day:hover,
.flatpickr-day.prevMonthDay:hover,
.flatpickr-day.nextMonthDay:hover,
.flatpickr-day:focus,
.flatpickr-day.prevMonthDay:focus,
.flatpickr-day.nextMonthDay:focus {
cursor: pointer;
outline: 0;
background: rgba(64, 187, 107);
border-color: rgba(64, 187, 107);
color: #fff;
}
.flatpickr-day.today {
border-color: rgba(64, 187, 107, 0.8);
}
.flatpickr-day.today:hover,
.flatpickr-day.today:focus {
border-color: rgba(64, 187, 107, 0.8);
background: rgba(64, 187, 107, 0.8);
color: #fff;
}
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.startRange.inRange,
.flatpickr-day.endRange.inRange,
.flatpickr-day.startRange:focus,
.flatpickr-day.endRange:focus,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.startRange.prevMonthDay,
.flatpickr-day.endRange.prevMonthDay,
.flatpickr-day.startRange.nextMonthDay,
.flatpickr-day.endRange.nextMonthDay {
background: #40bb6b;
-webkit-box-shadow: none;
box-shadow: none;
color: #fff;
border-color: #40bb6b;
}
.flatpickr-day.selected,
.flatpickr-day.selected.inRange,
.flatpickr-day.selected:focus,
.flatpickr-day.selected:hover,
.flatpickr-day.selected.prevMonthDay,
.flatpickr-day.selected.nextMonthDay {
background: #2f864e;
-webkit-box-shadow: none;
box-shadow: none;
color: #fff;
border-color: #2f864e;
}
.flatpickr-day.selected.startRange,
.flatpickr-day.startRange.startRange,
.flatpickr-day.endRange.startRange {
border-radius: 50px 0 0 50px;
}
.flatpickr-day.selected.endRange,
.flatpickr-day.startRange.endRange,
.flatpickr-day.endRange.endRange {
border-radius: 0 50px 50px 0;
}
.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n + 1)),
.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n + 1)),
.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n + 1)) {
-webkit-box-shadow: -10px 0 0 #085577;
box-shadow: -10px 0 0 #085577;
}
.flatpickr-day.selected.startRange.endRange,
.flatpickr-day.startRange.startRange.endRange,
.flatpickr-day.endRange.startRange.endRange {
border-radius: 50px;
}
.flatpickr-day.inRange {
border-radius: 0;
-webkit-box-shadow: -5px 0 0 #e2e2e2, 5px 0 0 #e2e2e2;
box-shadow: -5px 0 0 #e2e2e2, 5px 0 0 #e2e2e2;
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay,
.flatpickr-day.notAllowed,
.flatpickr-day.notAllowed.prevMonthDay,
.flatpickr-day.notAllowed.nextMonthDay {
color: rgba(72, 72, 72, 0.5);
background: transparent;
border-color: transparent;
cursor: default;
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover {
cursor: not-allowed;
color: rgba(72, 72, 72, 0.1);
}
.flatpickr-day.week.selected {
border-radius: 0;
-webkit-box-shadow: -5px 0 0 #085577, 5px 0 0 #085577;
box-shadow: -5px 0 0 #085577, 5px 0 0 #085577;
}
.flatpickr-day.hidden {
visibility: hidden;
}
.rangeMode .flatpickr-day {
margin-top: 1px;
}
.flatpickr-weekwrapper {
float: left;
}
.flatpickr-weekwrapper .flatpickr-weeks {
padding: 0 12px;
border-left: 1px solid rgba(72, 72, 72, 0.2);
}
.flatpickr-weekwrapper .flatpickr-weekday {
float: none;
width: 100%;
line-height: 28px;
}
.flatpickr-weekwrapper span.flatpickr-day,
.flatpickr-weekwrapper span.flatpickr-day:hover {
display: block;
width: 100%;
max-width: none;
color: rgba(72, 72, 72, 0.3);
background: transparent;
cursor: default;
border: none;
}
.flatpickr-innerContainer {
display: block;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
background: #fff;
border-bottom: 1px solid rgba(72, 72, 72, 0.2);
}
.flatpickr-rContainer {
display: inline-block;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.flatpickr-time {
text-align: center;
outline: 0;
display: block;
height: 0;
line-height: 40px;
max-height: 40px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
background: #fff;
border-radius: 0 0 5px 5px;
}
.flatpickr-time:after {
content: "";
display: table;
clear: both;
}
.flatpickr-time .numInputWrapper {
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
width: 40%;
height: 40px;
float: left;
}
.flatpickr-time .numInputWrapper span.arrowUp:after {
border-bottom-color: #484848;
}
.flatpickr-time .numInputWrapper span.arrowDown:after {
border-top-color: #484848;
}
.flatpickr-time.hasSeconds .numInputWrapper {
width: 26%;
}
.flatpickr-time.time24hr .numInputWrapper {
width: 49%;
}
.flatpickr-time input {
background: transparent;
-webkit-box-shadow: none;
box-shadow: none;
border: 0;
border-radius: 0;
text-align: center;
margin: 0;
padding: 0;
height: inherit;
line-height: inherit;
color: #484848;
font-size: 14px;
position: relative;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
.flatpickr-time input.flatpickr-hour {
font-weight: bold;
}
.flatpickr-time input.flatpickr-minute,
.flatpickr-time input.flatpickr-second {
font-weight: 400;
}
.flatpickr-time input:focus {
outline: 0;
border: 0;
}
.flatpickr-time-separator {
margin-left: 8px;
font-size: 16px;
}
.flatpickr-time .flatpickr-time-separator,
.flatpickr-time .flatpickr-am-pm {
height: inherit;
float: left;
line-height: inherit;
color: #484848;
font-weight: bold;
width: 2%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-align-self: center;
-ms-flex-item-align: center;
align-self: center;
}
.flatpickr-time .flatpickr-am-pm {
outline: 0;
width: 18%;
cursor: pointer;
text-align: center;
font-weight: 400;
}
.flatpickr-time input:hover,
.flatpickr-time .flatpickr-am-pm:hover,
.flatpickr-time input:focus,
.flatpickr-time .flatpickr-am-pm:focus {
background: #eaeaea;
}
.flatpickr-input[readonly] {
cursor: pointer;
}
@-webkit-keyframes fpFadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fpFadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}

View file

@ -0,0 +1,830 @@
.dark .flatpickr-calendar {
background: transparent;
opacity: 0;
display: none;
text-align: center;
visibility: hidden;
padding: 0;
-webkit-animation: none;
animation: none;
direction: ltr;
border: 0;
font-size: 14px;
line-height: 24px;
border-radius: 5px;
position: absolute;
width: 307.875px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-ms-touch-action: manipulation;
touch-action: manipulation;
background: #3f4458;
-webkit-box-shadow: 1px 0 0 #20222c, -1px 0 0 #20222c, 0 1px 0 #20222c,
0 -1px 0 #20222c, 0 3px 13px rgba(0, 0, 0, 0.08);
box-shadow: 1px 0 0 #20222c, -1px 0 0 #20222c, 0 1px 0 #20222c,
0 -1px 0 #20222c, 0 3px 13px rgba(0, 0, 0, 0.08);
}
.dark .flatpickr-calendar.open,
.dark .flatpickr-calendar.inline {
opacity: 1;
max-height: 640px;
visibility: visible;
}
.dark .flatpickr-calendar.open {
display: inline-block;
z-index: 99999;
}
.dark .flatpickr-calendar.animate.open {
-webkit-animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
animation: fpFadeInDown 300ms cubic-bezier(0.23, 1, 0.32, 1);
}
.dark .flatpickr-calendar.inline {
display: block;
position: relative;
top: 2px;
}
.dark .flatpickr-calendar.static {
position: absolute;
top: calc(100% + 2px);
}
.dark .flatpickr-calendar.static.open {
z-index: 999;
display: block;
}
.dark
.flatpickr-calendar.multiMonth
.flatpickr-days
.dayContainer:nth-child(n + 1)
.flatpickr-day.inRange:nth-child(7n + 7) {
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.dark
.flatpickr-calendar.multiMonth
.flatpickr-days
.dayContainer:nth-child(n + 2)
.flatpickr-day.inRange:nth-child(7n + 1) {
-webkit-box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
box-shadow: -2px 0 0 #e6e6e6, 5px 0 0 #e6e6e6;
}
.dark .flatpickr-calendar .hasWeeks .dayContainer,
.dark .flatpickr-calendar .hasTime .dayContainer {
border-bottom: 0;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.dark .flatpickr-calendar .hasWeeks .dayContainer {
border-left: 0;
}
.dark .flatpickr-calendar.hasTime .flatpickr-time {
height: 40px;
border-top: 1px solid #20222c;
background-color: #1e3969;
}
.dark .flatpickr-calendar.noCalendar.hasTime .flatpickr-time {
height: auto;
}
.dark .flatpickr-calendar:before,
.dark .flatpickr-calendar:after {
position: absolute;
display: block;
pointer-events: none;
border: solid transparent;
content: "";
height: 0;
width: 0;
left: 22px;
}
.dark .flatpickr-calendar.rightMost:before,
.dark .flatpickr-calendar.arrowRight:before,
.dark .flatpickr-calendar.rightMost:after,
.dark .flatpickr-calendar.arrowRight:after {
left: auto;
right: 22px;
}
.dark .flatpickr-calendar.arrowCenter:before,
.dark .flatpickr-calendar.arrowCenter:after {
left: 50%;
right: 50%;
}
.dark .flatpickr-calendar:before {
border-width: 5px;
margin: 0 -5px;
}
.dark .flatpickr-calendar:after {
border-width: 4px;
margin: 0 -4px;
}
.dark .flatpickr-calendar.arrowTop:before,
.dark .flatpickr-calendar.arrowTop:after {
bottom: 100%;
}
.dark .flatpickr-calendar.arrowTop:before {
border-bottom-color: #20222c;
}
.dark .flatpickr-calendar.arrowTop:after {
border-bottom-color: #3f4458;
}
.dark .flatpickr-calendar.arrowBottom:before,
.dark .flatpickr-calendar.arrowBottom:after {
top: 100%;
}
.dark .flatpickr-calendar.arrowBottom:before {
border-top-color: #20222c;
}
.dark .flatpickr-calendar.arrowBottom:after {
border-top-color: #3f4458;
}
.dark .flatpickr-calendar:focus {
outline: 0;
}
.dark .flatpickr-wrapper {
position: relative;
display: inline-block;
}
.dark .flatpickr-months {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.dark .flatpickr-months .flatpickr-month {
background: #085577;
color: #fff;
fill: #fff;
height: 34px;
line-height: 1;
text-align: center;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.dark .flatpickr-months .flatpickr-prev-month,
.dark .flatpickr-months .flatpickr-next-month {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-decoration: none;
cursor: pointer;
position: absolute;
top: -3px;
height: 34px;
padding: 10px;
z-index: 3;
color: #fff;
fill: #fff;
}
.dark .flatpickr-months .flatpickr-prev-month.flatpickr-disabled,
.dark .flatpickr-months .flatpickr-next-month.flatpickr-disabled {
display: none;
}
.dark .flatpickr-months .flatpickr-prev-month i,
.dark .flatpickr-months .flatpickr-next-month i {
position: relative;
}
.dark .flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,
.dark .flatpickr-months .flatpickr-next-month.flatpickr-prev-month {
/*
/*rtl:begin:ignore*/
/*
*/
left: 0;
/*
/*rtl:end:ignore*/
/*
*/
}
/*
/*rtl:begin:ignore*/
/*
/*rtl:end:ignore*/
.dark .flatpickr-months .flatpickr-prev-month.flatpickr-next-month,
.dark .flatpickr-months .flatpickr-next-month.flatpickr-next-month {
/*
/*rtl:begin:ignore*/
/*
*/
right: 0;
/*
/*rtl:end:ignore*/
/*
*/
}
/*
/*rtl:begin:ignore*/
/*
/*rtl:end:ignore*/
.dark .flatpickr-months .flatpickr-prev-month:hover,
.dark .flatpickr-months .flatpickr-next-month:hover {
color: #eee;
}
.dark .flatpickr-months .flatpickr-prev-month:hover svg,
.dark.flatpickr-months .flatpickr-next-month:hover svg {
fill: #40bb6b;
}
.dark .flatpickr-months .flatpickr-prev-month svg,
.dark .flatpickr-months .flatpickr-next-month svg {
width: 14px;
height: 14px;
}
.dark .flatpickr-months .flatpickr-prev-month svg path,
.dark .flatpickr-months .flatpickr-next-month svg path {
-webkit-transition: fill 0.1s;
transition: fill 0.1s;
fill: inherit;
}
.dark .numInputWrapper {
position: relative;
height: auto;
margin-left: 12px;
}
.dark .numInputWrapper input,
.dark .numInputWrapper span {
display: inline-block;
}
.dark .numInputWrapper input {
width: 100%;
}
.dark .numInputWrapper input::-ms-clear {
display: none;
}
.dark .numInputWrapper input::-webkit-outer-spin-button,
.dark .numInputWrapper input::-webkit-inner-spin-button {
margin: 0;
-webkit-appearance: none;
}
.dark .flatpickr-current-month .numInputWrapper span {
border:0
}
.dark .numInputWrapper span {
position: absolute;
right: 0;
width: 14px;
padding: 0 4px 0 2px;
height: 50%;
line-height: 50%;
opacity: 0;
cursor: pointer;
border-right: 1px solid rgba(26, 25, 25, 0.4);
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.dark .numInputWrapper span:hover {
background: rgba(192, 187, 167, 0.1);
}
.dark .numInputWrapper span:active {
background: rgba(192, 187, 167, 0.2);
}
.dark .numInputWrapper span:after {
display: block;
content: "";
position: absolute;
}
.dark .numInputWrapper span.arrowUp {
top: 0;
border-bottom: 0;
}
.dark .numInputWrapper span.arrowUp:after {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 4px solid rgba(255, 255, 255, 0.6);
top: 26%;
}
.dark .numInputWrapper span.arrowDown {
top: 50%;
}
.dark .numInputWrapper span.arrowDown:after {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid rgba(255, 255, 255, 0.6);
top: 40%;
}
.dark .numInputWrapper span svg {
width: inherit;
height: auto;
}
.dark .numInputWrapper span svg path {
fill: rgba(255, 255, 255, 0.5);
}
.dark .numInputWrapper:hover {
background: rgba(192, 187, 167, 0.05);
}
.dark .numInputWrapper span {
opacity: 1;
}
.dark .flatpickr-current-month {
z-index: 1000;
font-size: 16px;
line-height: inherit;
font-weight: 300;
color: inherit;
position: absolute;
width: 75%;
left: 12.5%;
padding: 7.48px 0 0 0;
line-height: 1;
height: 34px;
display: inline-block;
text-align: center;
-webkit-transform: translate3d(0px, 0px, 0px);
transform: translate3d(0px, 0px, 0px);
}
.dark .flatpickr-current-month span.cur-month {
font-family: inherit;
font-weight: 700;
color: inherit;
display: inline-block;
margin-left: 0.5ch;
padding: 0;
}
.dark .flatpickr-current-month span.cur-month:hover {
background: rgba(192, 187, 167, 0.05);
}
.dark .flatpickr-current-month .numInputWrapper {
width: 6ch;
width: 7ch\0;
display: inline-block;
}
.dark .flatpickr-current-month .numInputWrapper span.arrowUp:after {
border-bottom-color: #fff;
}
.dark .flatpickr-current-month .numInputWrapper span.arrowDown:after {
border-top-color: #fff;
}
.dark .flatpickr-current-month input.cur-year {
background: transparent;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: inherit;
cursor: text;
padding-right: 4px;
margin: 0;
display: inline-block;
font-size: inherit;
font-family: inherit;
font-weight: 300;
line-height: inherit;
height: auto;
border: 0;
border-radius: 0;
vertical-align: initial;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
.dark .flatpickr-current-month input.cur-year:focus {
outline: 0;
}
.dark .flatpickr-current-month input.cur-year[disabled],
.dark .flatpickr-current-month input.cur-year[disabled]:hover {
font-size: 100%;
color: rgba(255, 255, 255, 0.5);
background: transparent;
pointer-events: none;
}
.dark .flatpickr-current-month .flatpickr-monthDropdown-months {
appearance: menulist;
background: #085577;
border: none;
border-radius: 0;
box-sizing: border-box;
color: inherit;
cursor: pointer;
font-size: inherit;
font-family: inherit;
font-weight: 300;
height: auto;
line-height: inherit;
margin: -1px 0 0 0;
outline: none;
padding: 0 0 0 0.5ch;
position: relative;
vertical-align: initial;
-webkit-box-sizing: border-box;
-webkit-appearance: menulist;
-moz-appearance: menulist;
width: auto;
}
.dark .flatpickr-current-month .flatpickr-monthDropdown-months:focus,
.dark .flatpickr-current-month .flatpickr-monthDropdown-months:active {
outline: none;
}
.dark .flatpickr-current-month .flatpickr-monthDropdown-months:hover {
background: rgba(192, 187, 167, 0.05);
}
.dark
.flatpickr-current-month
.flatpickr-monthDropdown-months
.flatpickr-monthDropdown-month {
background-color: #085577;
outline: none;
padding: 0;
}
.dark .flatpickr-weekdays {
background: #085577;
text-align: center;
overflow: hidden;
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
height: 28px;
}
.dark .flatpickr-weekdays .flatpickr-weekdaycontainer {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.dark span.flatpickr-weekday {
cursor: default;
font-size: 90%;
background: #085577;
color: #fff;
line-height: 1;
margin: 0;
text-align: center;
display: block;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
font-weight: bolder;
}
.dark .dayContainer {
background: #1e3969;
}
.dark .dayContainer,
.flatpickr-weeks {
padding: 1px 0 0 0;
}
.dark .flatpickr-days {
position: relative;
overflow: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-align: start;
-webkit-align-items: flex-start;
-ms-flex-align: start;
align-items: flex-start;
width: 307.875px;
border: none;
}
.dark .flatpickr-days:focus {
outline: 0;
}
.dark .dayContainer {
padding: 3px;
outline: 0;
text-align: left;
width: 307.875px;
min-width: 307.875px;
max-width: 307.875px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
display: inline-block;
display: -ms-flexbox;
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
-ms-flex-wrap: wrap;
-ms-flex-pack: justify;
-webkit-justify-content: space-around;
justify-content: space-around;
-webkit-transform: translate3d(0px, 0px, 0px);
transform: translate3d(0px, 0px, 0px);
opacity: 1;
}
.dark .dayContainer + .dark .dayContainer {
-webkit-box-shadow: -1px 0 0 #20222c;
box-shadow: -1px 0 0 #20222c;
}
.dark .flatpickr-day {
background: none;
border: 1px solid transparent;
border-radius: 150px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
color: rgba(255, 255, 255, 0.95);
cursor: pointer;
font-weight: 400;
width: 14.2857143%;
-webkit-flex-basis: 14.2857143%;
-ms-flex-preferred-size: 14.2857143%;
flex-basis: 14.2857143%;
max-width: 39px;
height: 39px;
line-height: 39px;
margin: 1.5px;
display: inline-block;
position: relative;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
text-align: center;
}
.dark .flatpickr-day.inRange,
.dark .flatpickr-day.prevMonthDay.inRange,
.dark .flatpickr-day.nextMonthDay.inRange,
.dark .flatpickr-day.today.inRange,
.dark .flatpickr-day.prevMonthDay.today.inRange,
.dark .flatpickr-day.nextMonthDay.today.inRange,
.dark .flatpickr-day:hover,
.dark .flatpickr-day.prevMonthDay:hover,
.dark .flatpickr-day.nextMonthDay:hover,
.dark .flatpickr-day:focus,
.dark .flatpickr-day.prevMonthDay:focus,
.dark .flatpickr-day.nextMonthDay:focus {
cursor: pointer;
outline: 0;
background: rgba(64, 187, 107);
border-color: rgba(64, 187, 107);
color: #fff;
}
.dark .flatpickr-day.today {
border-color: rgba(64, 187, 107, 0.8);
}
.dark .flatpickr-day.today:hover,
.dark .flatpickr-day.today:focus {
border-color: rgba(64, 187, 107, 0.8);
background: rgba(64, 187, 107, 0.8);
color: #fff;
}
.dark .flatpickr-day.startRange,
.dark .flatpickr-day.endRange,
.dark .flatpickr-day.startRange.inRange,
.dark .flatpickr-day.endRange.inRange,
.dark .flatpickr-day.startRange:focus,
.dark .flatpickr-day.endRange:focus,
.dark .flatpickr-day.startRange:hover,
.dark .flatpickr-day.endRange:hover,
.dark .flatpickr-day.startRange.prevMonthDay,
.dark .flatpickr-day.endRange.prevMonthDay,
.dark .flatpickr-day.startRange.nextMonthDay,
.dark .flatpickr-day.endRange.nextMonthDay {
background: #40bb6b;
-webkit-box-shadow: none;
box-shadow: none;
color: #fff;
border-color: #40bb6b;
}
.dark .flatpickr-day.selected,
.dark .flatpickr-day.selected.inRange,
.dark .flatpickr-day.selected:focus,
.dark .flatpickr-day.selected:hover,
.dark .flatpickr-day.selected.prevMonthDay,
.dark .flatpickr-day.selected.nextMonthDay {
background: #2f864e;
-webkit-box-shadow: none;
box-shadow: none;
color: #fff;
border-color: #2f864e;
}
.dark .flatpickr-day.selected.startRange,
.dark .flatpickr-day.startRange.startRange,
.dark .flatpickr-day.endRange.startRange {
border-radius: 50px 0 0 50px;
}
.dark .flatpickr-day.selected.endRange,
.dark .flatpickr-day.startRange.endRange,
.dark .flatpickr-day.endRange.endRange {
border-radius: 0 50px 50px 0;
}
.dark .flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n + 1)),
.dark .flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n + 1)),
.dark .flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n + 1)) {
-webkit-box-shadow: -10px 0 0 #80cbc4;
box-shadow: -10px 0 0 #80cbc4;
}
.dark .flatpickr-day.selected.startRange.endRange,
.dark .flatpickr-day.startRange.startRange.endRange,
.dark .flatpickr-day.endRange.startRange.endRange {
border-radius: 50px;
}
.dark .flatpickr-day.inRange {
border-radius: 0;
-webkit-box-shadow: -5px 0 0 #646c8c, 5px 0 0 #646c8c;
box-shadow: -5px 0 0 #646c8c, 5px 0 0 #646c8c;
}
.dark .flatpickr-day.flatpickr-disabled,
.dark .flatpickr-day.flatpickr-disabled:hover,
.dark .flatpickr-day.prevMonthDay,
.dark .flatpickr-day.nextMonthDay,
.dark .flatpickr-day.notAllowed,
.dark .flatpickr-day.notAllowed.prevMonthDay,
.dark .flatpickr-day.notAllowed.nextMonthDay {
color: rgba(255, 255, 255, 0.5);
background: transparent;
border-color: transparent;
cursor: default;
}
.dark .flatpickr-day.flatpickr-disabled,
.dark .flatpickr-day.flatpickr-disabled:hover {
cursor: not-allowed;
color: rgba(255, 255, 255, 0.1);
}
.dark .flatpickr-day.week.selected {
border-radius: 0;
-webkit-box-shadow: -5px 0 0 #80cbc4, 5px 0 0 #80cbc4;
box-shadow: -5px 0 0 #80cbc4, 5px 0 0 #80cbc4;
}
.dark .flatpickr-day.hidden {
visibility: hidden;
}
.dark .rangeMode .flatpickr-day {
margin-top: 1px;
}
.dark .flatpickr-weekwrapper {
float: left;
}
.dark .flatpickr-weekwrapper .flatpickr-weeks {
padding: 0 12px;
-webkit-box-shadow: 1px 0 0 #20222c;
box-shadow: 1px 0 0 #20222c;
}
.dark .flatpickr-weekwrapper .flatpickr-weekday {
float: none;
width: 100%;
line-height: 28px;
}
.dark .flatpickr-weekwrapper span.flatpickr-day,
.dark .flatpickr-weekwrapper span.flatpickr-day:hover {
display: block;
width: 100%;
max-width: none;
color: rgba(255, 255, 255, 0.3);
background: transparent;
cursor: default;
border: none;
}
.dark .flatpickr-innerContainer {
display: block;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
border-bottom: none;
}
.dark .flatpickr-rContainer {
display: inline-block;
padding: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.dark .flatpickr-time {
text-align: center;
outline: 0;
display: block;
height: 0;
line-height: 40px;
max-height: 40px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.dark .flatpickr-time:after {
content: "";
display: table;
clear: both;
}
.dark .flatpickr-time .numInputWrapper {
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
width: 40%;
height: 40px;
float: left;
}
.dark .flatpickr-time .numInputWrapper span.arrowUp:after {
border-bottom-color: rgba(255, 255, 255, 0.95);
}
.dark .flatpickr-time .numInputWrapper span.arrowDown:after {
border-top-color: rgba(255, 255, 255, 0.95);
}
.dark .flatpickr-time.hasSeconds .numInputWrapper {
width: 26%;
}
.dark .flatpickr-time.time24hr .numInputWrapper {
width: 49%;
}
.dark .flatpickr-time input {
background: transparent;
-webkit-box-shadow: none;
box-shadow: none;
border: 0;
border-radius: 0;
text-align: center;
margin: 0;
padding: 0;
height: inherit;
line-height: inherit;
color: rgba(255, 255, 255, 0.95);
font-size: 14px;
position: relative;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
.dark .flatpickr-time input.flatpickr-hour {
font-weight: bold;
}
.dark .flatpickr-time input.flatpickr-minute,
.dark .flatpickr-time input.flatpickr-second {
font-weight: 400;
}
.dark .flatpickr-time input:focus {
outline: 0;
border: 0;
}
.dark .flatpickr-time .flatpickr-time-separator,
.dark .flatpickr-time .flatpickr-am-pm {
height: inherit;
float: left;
line-height: inherit;
color: rgba(255, 255, 255, 0.95);
font-weight: bold;
width: 2%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-align-self: center;
-ms-flex-item-align: center;
align-self: center;
}
.dark .flatpickr-time .flatpickr-am-pm {
outline: 0;
width: 18%;
cursor: pointer;
text-align: center;
font-weight: 400;
}
.dark .flatpickr-time input:hover,
.dark .flatpickr-time .flatpickr-am-pm:hover,
.dark .flatpickr-time input:focus,
.dark .flatpickr-time .flatpickr-am-pm:focus {
background: rgba(64, 187, 107, 0.8);
}
.dark .flatpickr-input[readonly] {
cursor: pointer;
}
@-webkit-keyframes fpFadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
@keyframes fpFadeInDown {
from {
opacity: 0;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
to {
opacity: 1;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}

View file

@ -0,0 +1,53 @@
<script setup>
/*
COMPONENT DESCRIPTION
*
*
This error field component is used to show a feedback message to the user when the field is invalid.
*
*
PROPS ARGUMENTS
*
*
isValid: boolean,
isValue: boolean,
*
*
PROPS EXAMPLE
*
*
isValid: false,
isValue: false,
*
*
*/
const props = defineProps({
isValid: {
type: Boolean,
required: false,
},
isValue : {
type: Boolean,
required: false,
}
})
</script>
<template>
<p
:aria-hidden="props.isValid ? 'true' : 'false'"
role="alert"
:class="[props.isValid ? 'hidden' : '']"
class="input-error-msg"
>
{{
props.isValid
? $t("inp_input_valid")
: !props.isValue
? $t("inp_input_error_required")
: $t("inp_input_error")
}}
</p>
</template>

View file

@ -3,6 +3,7 @@ import { reactive, defineProps, onMounted, ref } from "vue";
import { contentIndex } from "@utils/tabindex.js";
import Container from "@components/Widget/Container.vue";
import Header from "@components/Forms/Header/Field.vue";
import ErrorField from "@components/Forms/Error/Field.vue";
/*
COMPONENT DESCRIPTION
@ -32,6 +33,22 @@ import Header from "@components/Forms/Header/Field.vue";
*
*
PROPS EXAMPLE
*
*
{
containerClass : "",
columns : {"pc": 6, "tablet": 12, "mobile": 12},
id:"test-check",
value: "yes",
label: "Checkbox",
name: "checkbox",
required: true,
version: "v1.0.0",
hideLabel: false,
headerClass: "text-red-500"
}
*
*
*/
const props = defineProps({
@ -68,6 +85,7 @@ const props = defineProps({
version: {
type: String,
required: false,
default : ""
},
hideLabel: {
type: Boolean,
@ -75,19 +93,23 @@ const props = defineProps({
},
containerClass : {
type: String,
required: false
required: false,
default : ""
},
headerClass: {
type: String,
required: false,
default : ""
},
inpClass: {
type: String,
required: false,
default : ""
},
tabId: {
type: [String, Number],
required: false,
default: ""
},
});
@ -149,18 +171,7 @@ onMounted(() => {
d="M470.6 105.4c12.5 12.5 12.5 32.8 0 45.3l-256 256c-12.5 12.5-32.8 12.5-45.3 0l-128-128c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0L192 338.7 425.4 105.4c12.5-12.5 32.8-12.5 45.3 0z"
></path>
</svg>
<p
:aria-hidden="checkbox.isValid ? 'true' : 'false'"
role="alert"
:class="[checkbox.isValid ? 'hidden' : '']"
class="input-error-msg"
>
{{
checkbox.isValid
? $t("inp_input_valid")
: $t("inp_input_error_required")
}}
</p>
<ErrorField :isValid="checkbox.isValid" :isValue="checkbox.isValid" />
</div>
</Container>
</template>

View file

@ -0,0 +1,671 @@
<script setup>
import { reactive, defineEmits, defineProps, onMounted } from "vue";
import { contentIndex } from "@utils/tabindex.js";
import Container from "@components/Widget/Container.vue";
import Header from "@components/Forms/Header/Field.vue";
import ErrorField from "@components/Forms/Error/Field.vue";
import flatpickr from "flatpickr";
import "@assets/css/datepicker-foundation.css";
import "@assets/css/flatpickr.css";
import "@assets/css/flatpickr.dark.css";
/*
COMPONENT DESCRIPTION
*
*
This datepicker component is used to create a complete datepicker (label, validator message).
You can define a default date, a min and max date, and a format.
*
*
PROPS ARGUMENTS
*
*
id: string,
name: string,
label: string,
hideLabel: boolean,
headerClass: string,
containerClass: string,
columns: object || boolean,
disabled: boolean,
required: boolean,
defaultDate: string || number || date,
noPickBeforeStamp: string || number,
noPickAfterStamp: string || number,
inpClass: string,
tabId: string || number,
*
*
PROPS EXAMPLE
*
*
{
id: 'test-date',
containerClass : "",
columns : {"pc": 6, "tablet": 12, "mobile": 12},
disabled: false,
required: true,
defaultDate: 1735682600000,
noPickBeforeStamp: 1735682600000,
noPickAfterStamp: 1735689600000,
inpClass: "text-center",
tabId: "1",
}
*
*
*/
const props = defineProps({
// id && type && disabled && required && value
id: {
type: String,
required: true,
},
name : {
type: String,
required: false,
},
label: {
type: String,
required: false,
},
hideLabel: {
type: Boolean,
required: false,
},
headerClass: {
type: String,
required: false,
default: "",
},
containerClass: {
type: String,
required: false,
default: "",
},
inpClass: {
type: String,
required: false,
default: "",
},
columns: {
type: [Object, Boolean],
required: false,
default : false
},
disabled: {
type: Boolean,
required: false,
},
required: {
type: Boolean,
required: false,
},
defaultDate: {
type: [String, Number, Date],
required: false,
default: null,
},
// Impossible to pick a date before this date
noPickBeforeStamp: {
type: [String, Number],
required: false,
default: "",
},
// Impossible to pick a date after this date
noPickAfterStamp: {
type: [String, Number],
required: false,
default: "",
},
tabId: {
type: [String, Number],
required: false,
default: ""
},
});
const date = reactive({
isValid: false,
format: "m/d/Y H:i:S",
});
const picker = reactive({
isOpen: false,
});
let datepicker;
onMounted(() => {
datepicker = flatpickr(`#${props.id}`, {
locale: "en",
dateFormat: date.format,
defaultDate: props.defaultDate || "",
enableTime: true,
enableSeconds: true,
time_24hr: true,
minuteIncrement: 1,
onChange(selectedDates, dateStr, instance) {
if(!dateStr && props.required) return date.isValid = false;
//Check if date is in interval
try {
const currStamp = Date.parse(dateStr);
// Check pick is before min allow
if (props.noPickBeforeStamp && currStamp < props.noPickBeforeStamp) {
return instance.setDate(props.noPickBeforeStamp);
}
// Check pick is after min allow
if (props.noPickAfterStamp && currStamp > props.noPickAfterStamp) {
return instance.setDate(props.noPickAfterStamp);
}
// Run whatever, if invalid this will override
date.isValid = true;
} catch (err) {}
},
onOpen(selectedDates, dateStr, instance) {
picker.isOpen = true;
// Focus on current date and update tabindex
try {
setIndex(instance.calendarContainer, contentIndex);
const baseFocus =
instance.calendarContainer.querySelector(".flatpickr-day.today") ||
instance.calendarContainer.querySelector(".flatpickr-day");
baseFocus.setAttribute("data-tabindex-active", true);
setTimeout(() => {
baseFocus.focus();
}, 50);
} catch (err) {}
},
onClose(selectedDates, dateStr, instance) {
picker.isOpen = false;
setIndex(instance.calendarContainer, "-1");
},
});
// Check if multiple or not
let datepickerEl = null;
if (Array.isArray(datepicker)) {
datepickerEl = datepicker[datepicker.length - 1];
} else {
datepickerEl = datepicker;
}
// Set valid date state
if (!datepickerEl.selectedDates[0] && props.required) date.isValid = false;
if (!datepickerEl.selectedDates[0] && !props.required) date.isValid = true;
const calendar = datepickerEl.calendarContainer;
// Impossible to use default select month dropdown with keyboard
// We need to create our own and link calendar to it
setMonthSelect(calendar, props.id);
// Override default behavior that go to input el instead of previous calendat element on tab + maj
handleEvents(calendar, props.id, datepickerEl);
setPickerAtt(calendar, props.id);
});
function setMonthSelect(calendar, id) {
// Hide default select and optionss
const defaultSelect = calendar.querySelector(
".flatpickr-monthDropdown-months",
);
defaultSelect.classList.add("hidden");
defaultSelect.setAttribute("aria-hidden", "true");
defaultSelect.setAttribute("tabindex", "-1");
defaultSelect.querySelectorAll("option").forEach((option) => {
option.classList.add("hidden");
option.setAttribute("tabindex", "-1");
option.setAttribute("aria-hidden", "true");
});
// Create custom select
// Container
const container = document.createElement("div");
container.classList.add(
"flatpickr-monthDropdown-months",
"inline",
"relative",
);
// Select-like
const selectCustom = document.createElement("button");
selectCustom.setAttribute("data-interactive", "");
selectCustom.setAttribute("aria-label", "Month");
selectCustom.setAttribute("data-months-select", "");
selectCustom.setAttribute("aria-controls", `${id}-custom`);
container.appendChild(selectCustom);
// Options container
const optCtnr = document.createElement("div");
optCtnr.setAttribute("role", "radiogroup");
optCtnr.setAttribute("id", `${id}-custom`);
optCtnr.classList.add("select-dropdown-container", "hidden", "flex");
container.appendChild(optCtnr);
// Options
calendar
.querySelector(".flatpickr-monthDropdown-months")
.querySelectorAll("option")
.forEach((option) => {
// Prepare options
const opt = document.createElement("button");
opt.classList.add(
"flatpickr-monthDropdown-month",
"rounded-none",
"text-white",
"py-1",
"hover:brightness-125",
"focus:brightness-125",
);
opt.setAttribute("data-month", option.value);
opt.setAttribute("data-value", option.value);
opt.setAttribute("data-interactive", "");
opt.setAttribute("role", "radio");
opt.setAttribute("aria-checked", option.selected ? "true" : "false");
opt.setAttribute("aria-label", option.textContent);
opt.setAttribute("aria-controls", `${id}-custom`);
opt.textContent = option.textContent;
// Set select as button content
if (option.selected) {
selectCustom.textContent = option.textContent;
}
// Append options
optCtnr.appendChild(opt);
});
// Insert as sibling of select
defaultSelect.parentNode.insertBefore(container, defaultSelect.nextSibling);
}
function setPickerAtt(calendarEl, id = false) {
// change error non-standard attributes
if (id) {
calendarEl.setAttribute("id", id);
}
const inps = calendarEl.querySelectorAll(
'input.numInput[type="number"][maxlength]',
);
inps.forEach((inp) => {
inp.setAttribute("data-maxlength", inp.getAttribute("maxlength"));
inp.removeAttribute("maxlength");
});
// set role button
calendarEl.querySelectorAll(".flatpickr-day").forEach((el) => {
el.setAttribute("role", "button");
});
calendarEl
.querySelector(".flatpickr-prev-month")
.setAttribute("role", "button");
calendarEl
.querySelector(".flatpickr-next-month")
.setAttribute("role", "button");
// Prevent svg to be focusable
calendarEl.querySelectorAll("svg").forEach((svg) => {
svg.classList.add("pointer-events-none");
});
}
function handleEvents(calendarEl, id, datepicker) {
calendarEl.addEventListener("click", (e) => {
// Close dropdown month select if click outside
closeSelectByDefault(calendarEl, id, e);
// Remove prev focus el and replace by click one if is tabindex element
updateIndex(calendarEl, e.target);
// When month change, update tabindex and update custom select
if (
e.target.classList.contains("flatpickr-prev-month") ||
e.target.classList.contains("flatpickr-next-month") ||
e.target.classList.contains("flatpickr-monthDropdown-month")
) {
setIndex(calendarEl, contentIndex);
}
// When click on next or prev month button
// Update custom select and options
if (
e.target.classList.contains("flatpickr-prev-month") ||
e.target.classList.contains("flatpickr-next-month")
) {
// Get update value
const selectDefault = calendarEl.querySelector(
"select.flatpickr-monthDropdown-months",
);
let monthValue;
let monthName;
selectDefault.querySelectorAll("option").forEach((option) => {
if (option.selected) {
monthValue = option.value;
monthName = option.textContent;
}
});
// Update options
calendarEl.querySelectorAll("[data-month]").forEach((el) => {
el.setAttribute("aria-checked", "false");
el.classList.remove("active");
if (el.getAttribute("data-month") === monthValue) {
el.setAttribute("aria-checked", "true");
el.classList.add("active");
}
});
// Update select text
const selectCustom = calendarEl.querySelector("[data-months-select]");
selectCustom.textContent = monthName;
selectCustom.focus();
}
// When click on custom select toggle
toggleSelect(calendarEl, id, e);
// When click on custom select option
updateMonth(calendarEl, id, e, datepicker);
});
calendarEl.addEventListener("keydown", (e) => {
// Space or enter logic
if (
(e.key !== "Tab" && !e.shiftKey && e.keyCode === 13) ||
(e.key !== "Tab" && !e.shiftKey && e.keyCode === 32)
) {
// Prev or next month button
if (
e.target.classList.contains("flatpickr-prev-month") ||
e.target.classList.contains("flatpickr-next-month")
) {
e.preventDefault();
e.target.click();
}
// Close dropdown month select if target isn't select
closeSelectByDefault(calendarEl, id, e);
// Custom select toggle
toggleSelect(calendarEl, id, e);
// Custom select option
updateMonth(calendarEl, id, e, datepicker);
}
let prevEl = null;
// Override default tab + maj behavior that focus input instead of previous calendar element
if (e.key === "Tab" && e.shiftKey) {
e.preventDefault();
const currActive = calendarEl.querySelector(
'[data-tabindex-active="true"]',
);
if (!currActive) return;
try {
// Case day, get prev day or next month el if no day remaining
if (currActive.classList.contains("flatpickr-day"))
prevEl =
currActive.previousElementSibling ||
calendarEl.querySelector(".flatpickr-next-month") ||
null;
// Case months
if (currActive.classList.contains("flatpickr-next-month"))
prevEl = calendarEl.querySelector(".cur-year") || null;
if (currActive.hasAttribute("data-months-select"))
prevEl = calendarEl.querySelector(".flatpickr-prev-month") || null;
if (currActive.hasAttribute("data-month"))
prevEl =
currActive.previousElementSibling ||
calendarEl.querySelector("[data-months-select]") ||
null;
// Case first datepicker element, go to input
if (currActive.classList.contains("flatpickr-prev-month"))
prevEl = null;
// Case year
if (currActive.classList.contains("cur-year"))
prevEl = calendarEl.querySelector("[data-months-select]") || null;
// Case hours
if (currActive.classList.contains("flatpickr-hour"))
prevEl =
calendarEl.querySelector(".dayContainer").lastElementChild || null;
// Case minutes
if (currActive.classList.contains("flatpickr-minute"))
prevEl = calendarEl.querySelector(".flatpickr-hour") || null;
// Case minutes
if (currActive.classList.contains("flatpickr-second"))
prevEl = calendarEl.querySelector(".flatpickr-minute") || null;
// Focus or close
if (prevEl) prevEl.focus();
if (!prevEl) {
//Focus previous element with a tabindex
const currIndex = datepicker.input.getAttribute("tabindex");
const elements = document.querySelectorAll(
`input[tabindex="${currIndex}"]`,
);
// Remove disabled elements
const filtered = [];
elements.forEach((el) => {
if (el === datepicker.input) return filtered.push(el);
if (
el.hasAttribute("disabled") ||
el.className.includes("flatpickr")
)
return;
filtered.push(el);
});
// Get previous element
let focusEl;
filtered.forEach((el, id) => {
if (el !== datepicker.input) return;
focusEl = filtered[id - 1];
});
// Focus new one
datepicker.close();
setTimeout(() => {
focusEl.focus();
}, 50);
}
} catch (e) {}
}
// Override when seconds
if (
e.keyCode === "Tab" &&
!e.shiftKey &&
calendarEl
.querySelector('[data-tabindex-active="true"]')
.classList.contains("flatpickr-second")
) {
try {
//Focus next element with a tabindex
const currIndex = datepicker.input.getAttribute("tabindex");
const elements = document.querySelectorAll(
`input[tabindex="${currIndex}"]`,
);
// Remove disabled elements
const filtered = [];
elements.forEach((el) => {
if (el === datepicker.input) return filtered.push(el);
if (el.hasAttribute("disabled") || el.className.includes("flatpickr"))
return;
filtered.push(el);
});
// Get next element
let focusEl;
filtered.forEach((el, id) => {
if (el !== datepicker.input) return;
focusEl = filtered[id + 1];
});
// Focus new one
datepicker.close();
setTimeout(() => {
focusEl.focus();
}, 50);
} catch (e) {}
}
// Global
setPickerAtt(calendarEl, false);
setIndex(calendarEl, contentIndex);
return updateIndex(calendarEl, prevEl || document.activeElement);
});
}
function toggleSelect(calendar, id, e) {
if (e.target.hasAttribute("data-months-select")) {
const optCtnr = calendar.querySelector(`#${id}-custom`);
optCtnr.classList.toggle("hidden");
optCtnr.setAttribute(
"aria-hidden",
optCtnr.classList.contains("hidden") ? "true" : "false",
);
}
}
function closeSelectByDefault(calendar, id, e) {
if (!e.target.hasAttribute("data-months-select")) {
const optCtnr = calendar.querySelector(`#${id}-custom`);
if (!optCtnr.classList.contains("hidden")) {
optCtnr.classList.add("hidden");
optCtnr.setAttribute("aria-hidden", "true");
}
}
}
function updateMonth(calendar, id, e, datepicker) {
if (e.target.hasAttribute("data-month")) {
// Close dropdown
const optCtnr = calendar.querySelector(`#${id}-custom`);
optCtnr.classList.add("hidden");
optCtnr.setAttribute("aria-hidden", "true");
// Update options
calendar.querySelectorAll("data-month").forEach((el) => {
el.setAttribute("aria-checked", "false");
el.classList.remove("active");
});
e.target.setAttribute("aria-checked", "true");
e.target.classList.add("active");
// Update select text
const selectCustom = calendar.querySelector("[data-months-select]");
selectCustom.textContent = e.target.textContent;
selectCustom.focus();
// Click on default select to update
const selectDefault = calendar.querySelector(
"select.flatpickr-monthDropdown-months",
);
selectDefault.querySelectorAll("option").forEach((option) => {
if (option.value === e.target.getAttribute("data-month")) {
datepicker.changeMonth(parseInt(option.value, 10) - 1, false);
option.selected = true;
}
});
}
}
function updateIndex(calendarEl, target) {
if (target.hasAttribute("tabindex")) {
calendarEl.querySelectorAll("[data-tabindex-active]").forEach((el) => {
el.removeAttribute("data-tabindex-active");
});
target.setAttribute("data-tabindex-active", true);
}
}
function setIndex(calendarEl, tabindex) {
try {
const days = calendarEl.querySelectorAll(".flatpickr-day");
days.forEach((day) => {
day.setAttribute("tabindex", tabindex);
});
} catch (e) {}
try {
const customSelectEls = calendarEl.querySelectorAll("[data-interactive]");
customSelectEls.forEach((el) => {
el.setAttribute("tabindex", tabindex);
});
} catch (err) {}
try {
const nextMonth = calendarEl.querySelector(".flatpickr-next-month");
const prevMonth = calendarEl.querySelector(".flatpickr-prev-month");
const year = calendarEl.querySelector(".cur-year");
const monthSelect = calendarEl.querySelector(
".flatpickr-monthDropdown-months",
);
prevMonth.setAttribute("tabindex", tabindex);
nextMonth.setAttribute("tabindex", tabindex);
year.setAttribute("tabindex", tabindex);
monthSelect.setAttribute("tabindex", tabindex);
const months = calendarEl.querySelectorAll(
".flatpickr-monthDropdown-month",
);
months.forEach((month) => {
month.setAttribute("tabindex", tabindex);
});
} catch (e) {}
try {
const hour = calendarEl.querySelector(".numInput.flatpickr-hour");
const minute = calendarEl.querySelector(".numInput.flatpickr-minute");
const second = calendarEl.querySelector(".numInput.flatpickr-second");
hour.setAttribute("tabindex", tabindex);
minute.setAttribute("tabindex", tabindex);
second.setAttribute("tabindex", tabindex);
} catch (e) {}
}
</script>
<template>
<Container :containerClass="`w-full m-1 p-1 ${props.containerClass}`" :columns="props.columns">
<Header :required="props.required" :name="props.name" :label="props.label" :hideLabel="props.hideLabel" :headerClass="props.headerClass" />
<div class="relative flex flex-col items-start">
<input
:tabindex="props.tabId || contentIndex"
:aria-controls="props.id"
:aria-selected="picker.isOpen ? 'true' : 'false'"
type="text"
:class="[
date.isValid ? 'valid' : 'invalid',
'input-regular',
props.inpClass,
props.disabled ? 'cursor-not-allowed' : 'cursor-pointer',
]"
:id="props.id"
:required="props.required || false"
:disabled="props.disabled || false"
:name="props.name"
:placeholder="'mm/dd/yyyy h:m:s'"
pattern="/^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/\d{4}$/g"
/>
<svg
aria-hidden="true"
role="img"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="w-6 h-6 stroke-gray-600 opacity-50 pointer-events-none absolute top-1 md:top-1.5 right-2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5"
/>
</svg>
<ErrorField :isValid="date.isValid" :isValue="!!date.value" />
</div>
</Container>
</template>

View file

@ -3,6 +3,7 @@ import { reactive, ref, defineEmits, onMounted, defineProps } from "vue";
import { contentIndex } from "@utils/tabindex.js";
import Container from "@components/Widget/Container.vue";
import Header from "@components/Forms/Header/Field.vue";
import ErrorField from "@components/Forms/Error/Field.vue";
/*
@ -115,19 +116,23 @@ const props = defineProps({
},
containerClass : {
type: String,
required: false
required: false,
default : ""
},
headerClass: {
type: String,
required: false,
default : ""
},
inpClass: {
type: String,
required: false,
default : ""
},
tabId: {
type: [String, Number],
required: false,
default : ""
},
});
@ -279,20 +284,7 @@ onMounted(() => {
</svg>
</button>
</div>
<p
:aria-hidden="inp.isValid ? 'true' : 'false'"
role="alert"
:class="[inp.isValid ? 'hidden' : '']"
class="input-error-msg"
>
{{
inp.isValid
? $t("inp_input_valid")
: !inp.value
? $t("inp_input_error_required")
: $t("inp_input_error_format")
}}
</p>
<ErrorField :isValid="inp.isValid" :isValue="!!inp.value" />
</div>
</Container>
</template>

View file

@ -3,6 +3,7 @@ import { ref, reactive, watch, onMounted, defineEmits, defineProps } from "vue";
import { contentIndex } from "@utils/tabindex.js";
import Container from "@components/Widget/Container.vue";
import Header from "@components/Forms/Header/Field.vue";
import ErrorField from "@components/Forms/Error/Field.vue";
/*
@ -22,6 +23,7 @@ import Header from "@components/Forms/Header/Field.vue";
values: array,
disabled: boolean,
required: boolean,
requiredValues : array,
label: string,
name: string,
version: string,
@ -42,6 +44,7 @@ import Header from "@components/Forms/Header/Field.vue";
name: 'test-input',
disabled: false,
required: true,
requiredValues : ['no'], // need required to be checked
label: 'Test select',
}
*
@ -76,6 +79,11 @@ const props = defineProps({
type: Boolean,
required: false,
},
requiredValues : {
type: Array,
required: false,
default : []
},
label: {
type: String,
required: true,
@ -87,6 +95,7 @@ const props = defineProps({
version: {
type: String,
required: false,
default : ""
},
hideLabel: {
type: Boolean,
@ -94,19 +103,23 @@ const props = defineProps({
},
containerClass : {
type: String,
required: false
required: false,
default : ""
},
headerClass: {
type: String,
required: false,
default : ""
},
inpClass: {
type: String,
required: false,
default : ""
},
tabId: {
type: [String, Number],
required: false,
default: ""
},
});
@ -128,6 +141,7 @@ const select = reactive({
// If we use select.value : props.value
// Component will not re-render after props.value change
value: "",
isValid: false,
});
const selectBtn = ref();
@ -146,6 +160,7 @@ function changeValue(newValue) {
// Allow on template to switch from prop value to component own value
// Then send the new value to parent
select.value = newValue;
// Check if value is required and if it is in requiredValueselect.isValid = !props.required ? true : props.requiredValues.includes(newValue) ? true : false;
closeSelect();
return newValue;
}
@ -211,7 +226,8 @@ const emits = defineEmits(["inp"]);
data-select-dropdown
:disabled="props.disabled || false"
@click="toggleSelect()"
:class="['select-btn', props.inpClass]"
:class="['select-btn', select.isValid ? 'valid' : 'invalid',
props.inpClass]"
>
<span :id="`${props.id}-text`" class="select-btn-name">
{{ select.value || props.value }}
@ -257,6 +273,8 @@ const emits = defineEmits(["inp"]);
{{ value }}
</button>
</div>
<ErrorField :isValisd="select.isValid" :isValue="true" />
<!-- end dropdown-->
</div>
<!-- end custom-->

View file

@ -2,11 +2,14 @@
import { defineProps } from "vue";
/*
COMPONENT DESCRIPTION
*
*
This header component is used with field in order to link a label to field type.
We can show additionnal data, like validaiton pattern with invalid message,
Or add some popovers elements.
*
*
PROPS ARGUMENTS
*
*
@ -19,6 +22,17 @@ import { defineProps } from "vue";
headerClass: string,
*
*
PROPS EXAMPLE
*
*
{
label: 'Test',
version : "0.1.0",
name: 'test-input',
required: true,
}
*
*
*/
const props = defineProps({

View file

@ -32,18 +32,17 @@ const props = defineProps({
})
const svgClass = computed(() => {
return `ml-2 w-6 h-6 ${props.iconColor}`
return `w-6.5 h-6.5 ${props.iconColor}`
})
</script>
<template>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
:class="[svgClass]">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
:class="[svgClass]">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</template>

View file

@ -1,8 +1,10 @@
<script setup>
import { computed, ref, watch, onBeforeMount, onMounted } from 'vue';
import Container from "@components/Widget/Container.vue";
import { contentIndex } from "@utils/tabindex.js";
import { useEventStore } from "@store/event.js";
import Container from "@components/Widget/Container.vue";
import IconAdd from "@components/Icons/Button/Add.vue";
/*
COMPONENT DESCRIPTION
@ -20,6 +22,7 @@ import { useEventStore } from "@store/event.js";
*
id: string,
text: string,
type: string<"button"|"submit">,
disabled: boolean,
hideText: boolean,
color: string,
@ -60,6 +63,11 @@ const props = defineProps({
type: String,
required: true
},
type : {
type: String,
required: false,
default : "button"
},
disabled : {
type: Boolean,
required: false,
@ -161,14 +169,17 @@ function updateData(isClick = false) {
</script>
<template>
<Container :containerClass="`w-full m-1 ${props.containerClass}`" :columns="props.columns">
<button ref="btnEl" @click="updateData(true)" :id="props.id"
<Container :containerClass="`w-full m-2 ${props.containerClass}`" :columns="props.columns">
<button :type="props.type" ref="btnEl" @click="updateData(true)" :id="props.id"
:tabindex="props.tabId || contentIndex"
:class="[buttonClass]"
:disabled="props.disabled || false"
:aria-describedby="`${props.id}-text`"
>
<span :class="[props.hideText ? 'sr-only' : '']" :id="`${props.id}-text`">{{ props.text }}</span>
<span :class="[props.hideText ? 'sr-only' : '',
props.iconName ? 'mr-2' : ''
]" :id="`${props.id}-text`">{{ props.text }}</span>
<IconAdd v-if="props.iconName === 'add'" :iconName="props.iconName" :iconColor="props.iconColor" />
</button>
</Container>
</template>

View file

@ -47,7 +47,7 @@ const gridClass = computed(() => {
</script>
<template>
<div :class="[props.containerClass, gridClass]">
<div :class="[props.containerClass ? props.containerClass : '', gridClass]">
<slot></slot>
</div>
</template>

View file

@ -59,7 +59,7 @@ const props = defineProps({
})
const containerClass = computed(() => {
if(props.type === 'card') return 'bg-white rounded shadow-md w-full';
if(props.type === 'card') return 'bg-white rounded-xl shadow-md w-full';
return '';
})
@ -68,14 +68,14 @@ const gridClass = computed(() => {
})
const titleClass = computed(() => {
if(props.type === 'card') return 'text-2xl font-bold text-center m-4';
if(props.type === 'card') return 'text-2xl font-bold mb-2';
return ''
})
</script>
<template>
<div :class="[containerClass, gridClass, props.gridLayoutClass]">
<h1 v-if="props.title" :class="[titleClass]">{{ props.title }}</h1>
<div :class="[containerClass, gridClass, props.gridLayoutClass, 'p-4 m-4']">
<h1 v-if="props.title" :class="[titleClass, 'col-span-12']">{{ props.title }}</h1>
<slot></slot>
</div>
</template>

View file

@ -344,10 +344,11 @@
"account_totp_secret_placeholder": "secret key",
"inp_select_default_desc": "Link to a custom visible select component. Shouldn't be used directly.",
"inp_select_dropdown_button_desc": "Custom dropdown toggle button.",
"inp_select_dropdown_desc" : "Custom dropdown list.",
"inp_input_password_desc": "Toggle show/hide password type and so value.",
"inp_input_clipboard_desc": "Copy value to clipboard.",
"inp_input_error_required": "Field is required",
"inp_input_error_format": "Invalid value format",
"inp_input_error": "Invalid value",
"inp_input_valid": "Valid input.",
"inp_select_label_empty": "Empty",
"inp_upload_add": "click or drag-n-drop",

View file

@ -1,340 +0,0 @@
{
"setup_loader_default": "Chargement",
"setup_loader_setup": "Mise en place...",
"setup_logo_alt": "BunkerWeb image logo",
"setup_title": "Assistant d'installation",
"setup_account": "Compte",
"setup_username": "identifiant",
"setup_username_placeholder": "identifiant",
"setup_password": "mot de passe",
"setup_password_placeholder": "mot de passe",
"setup_password_check": "confirmer mot de passe",
"setup_password_check_placeholder": "même que le précédent",
"setup_password_check_invalid": "La valeur ne correspond pas au précédent mot de passe",
"setup_settings": "Paramètres",
"setup_ui_host": "hôte dashboard (REVERSE_PROXY_HOST)",
"setup_ui_host_placeholder": "http://[nom_hôte](:[port])",
"setup_ui_url": "URL dashboard (REVERSE_PROXY_URL)",
"setup_ui_url_placeholder": "/admin",
"setup_server_name": "nom du serveur",
"setup_server_name_placeholder": "www.example.com",
"setup_server_name_value": "www.example.com",
"setup_check_dns": "Vérifier le DNS du serveur ",
"setup_check_dns_button": "Vérifier le DNS",
"setup_check_dns_color_desc": "Couleur du résultat de la vérification du DNS",
"setup_check_dns_result_unknown": "Le résultat de la vérification du DNS est inconnu",
"setup_check_dns_result_success": "Le résultat de la vérification du DNS est un succès",
"setup_check_dns_result_error": "Le résultat de la vérification du DNS est une erreur",
"setup_lets_encrypt": "Auto let's encrypt",
"setup_final_url": "Votre URL BunkerWeb final pour le dashboard est",
"setup_button": "Mettre en place",
"setup_form_invalid_submit": "Au moins un champ invalide ou manquant pour confirmer",
"setup_failed": "Erreur pendant l'installation. Réessayez plus tard.",
"login_title": "connexion",
"login_username": "identifiant",
"login_username_placeholder": "entrer identifiant",
"login_password": "mot de passe",
"login_password_placeholder": "entrer mot de passe",
"login_log_button": "se connecter",
"totp_error": "Le code du TOTP est invalide",
"totp_logo_alt": "BunkerWeb logo",
"totp_title": "Double authentification",
"totp_code ": "code",
"totp_code_placeholder": "954186",
"totp_button": "Envoyer",
"action_disable": "activer",
"action_enable": "désactiver",
"action_save": "sauvegarder",
"action_add": "ajouter",
"action_close": "fermer",
"action_delete": "supprimer",
"action_edit": "editer",
"action_download": "télécharger",
"action_create": "créer",
"action_view": "voir",
"action_stop": "stop",
"action_ping": "ping",
"action_reload": "reload",
"action_upload": "upload",
"action_delete_all": "supprimer tout",
"api_pending": "Tentative de récupération de(s) {name}",
"api_error": "Erreur de récupération de(s) {name}",
"api_pending_default": "Tentative de récupération des données",
"api_error_default": "Erreur de récupération des données",
"dashboard_logo_alt": "image du logo BunkerWeb",
"dashboard_logo_link_label": "Redirection vers l'accueil",
"dashboard_bw": "BunkerWeb",
"dashboard_docs": "docs",
"dashboard_blog": "blog",
"dashboard_privacy": "confidentialité",
"dashboard_license": "licence",
"dashboard_sitemap": "plan du site",
"dashboard_default": "défaut",
"dashboard_info": "info",
"dashboard_filter": "filtres",
"dashboard_advanced": "avancé",
"dashboard_loader": "chargement",
"dashboard_lang_dropdown_button_desc": "Toggle montre/cache le groupe radio (dropdown) pour changer de langue.",
"dashboard_refresh_desc": "rafraîchissement de toutes les données.",
"dashboard_home": "accueil",
"dashboard_instances": "instances",
"dashboard_global_config": "config globale",
"dashboard_services": "services",
"dashboard_configs": "configs",
"dashboard_plugins": "plugins",
"dashboard_jobs": "jobs",
"dashboard_bans": "bans",
"dashboard_actions": "actions",
"dashboard_account": "compte",
"dashboard_reporting": "rapports",
"dashboard_menu_toggle_sidebar": "Ouvrir/fermer la sidebar de menu.",
"dashboard_menu_close_sidebar": "Ferme la sidebar de menu.",
"dashboard_menu_twitter_label": "redirection vers le Twitter de BunkerWeb",
"dashboard_menu_linkedin_label": "redirection vers le Linkedin de BunkerWeb",
"dashboard_menu_discord_label": "redirection vers le Discord de BunkerWeb",
"dashboard_menu_github_label": "redirection vers le Github de BunkerWeb",
"dashboard_menu_plugins_title": "pages plugin",
"dashboard_menu_plugins_none": "envie de plugins custom ?",
"dashboard_menu_plugins_none_doc": "voir la doc",
"dashboard_menu_mode_light": "mode clair",
"dashboard_menu_mode_dark": "mode sombre",
"dashboard_menu_log_out": "se déconnecter",
"dashboard_actions_title": "actions",
"dashboard_actions_subtitle": "liste des feedbacks",
"dashboard_feedback_close_sidebar": "fermer la sidebar de feeback",
"dashboard_feedback_toggle_sidebar": "ouvrir/fermer la sidebar de feeback",
"dashboard_ui": "iu",
"dashboard_scheduler": "scheduler",
"dashboard_autoconf": "autoconf",
"dashboard_core": "core",
"dashboard_global": "global",
"dashboard_news_toggle_sidebar": "Ouvrir/fermer la sidebar de news.",
"dashboard_news_close_sidebar": "Ferme la sidebar de news.",
"dashboard_news_title": "news",
"dashboard_news_subtitle": "restez à jour !",
"dashboard_news_fetch_error": "Impossible de récupérer les news",
"dashboard_newsletter_title": "Rejoindre la newsletter",
"dashboard_newsletter_placeholder": "martin.dupont{'@'}example.com",
"dashboard_newsletter_privacy_text": "j'ai lu et accepte",
"dashboard_newsletter_privacy_text_link": "la politique de confidentialité",
"dashboard_newsletter_subscribe_button": "souscrire",
"dashboard_api_state_desc": "Montre les détails sur la récupération de données.",
"dashboard_alert_close_desc": "Ferme l'alerte.",
"dashboard_feedback_alert_desc": "Retour sur vos propres actions.",
"dashboard_feedback_logs_desc": "Retour sur les actions BunkerWeb.",
"dashboard_popover_button_desc": "Montre des détails sur les paramètres au survol.",
"dashboard_popover_button": "Montre un popover avec des détails sur le paramètre",
"dashboard_popover_detail_desc": "Un conteneur avec les détails sur le paramètre.",
"dashboard_up": "up",
"dashboard_down": "down",
"dashboard_banner_title_1": "Besoin de support premium ?",
"dashboard_banner_title_2": "Essayez Bunkerweb sur notre",
"dashboard_banner_title_3": "Toutes informations disponibles sur",
"dashboard_banner_link_1": "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui",
"dashboard_banner_link_2": "https://demo.bunkerweb.io/link/?utm_campaign=self&utm_source=ui",
"dashboard_banner_link_3": "https://www.bunkerweb.io/?utm_campaign=self&utm_source=ui",
"dashboard_banner_link_text_1": "BunkerWeb Panel est là !",
"dashboard_banner_link_text_2": "demo web app !",
"dashboard_banner_link_text_3": "notre website !",
"home_version_is_latest": "est la dernière version",
"home_version_latest_version": "dernière version",
"home_version": "version",
"home_internal": "internes",
"home_external": "externes",
"home_card_link_label": "redirection vers la page correspondante aux données",
"instances_hostname": "hostname",
"instances_method": "methode",
"instances_port": "port",
"instances_active": "instance active",
"instances_inactive": "instance inactive",
"instances_modal_delete_msg": "Etes-vous sûr de vouloir supprimer l'instance {hostname} ?",
"instances_modal_delete_title": "Supprimer l'instance",
"actions_total": "Actions total",
"actions_ui": "Actions IU",
"actions_core": "Actions CORE",
"actions_filter_title": "filtres",
"actions_filter_search": "rechercher",
"actions_filter_method": "methodes",
"actions_filter_api_method": "api methodes",
"actions_header_method": "methode",
"actions_header_title": "titre",
"actions_header_description": "description",
"actions_header_date": "date",
"actions_header_action": "action",
"actions_table_summary": "Détails des actions effectuées sur BunkerWeb (CORE, UI, CLI...)",
"bans_list": "Liste des bans",
"bans_add_bans": "Ajouter des bans",
"bans_add_entry": "Ajouter une entrée",
"bans_instances_total": "Total instances",
"bans_ip_bans_total": "Total ip bans",
"bans_filter_title": "Filtres liste des bans",
"bans_filter_search_ip": "rechercher par ip",
"bans_filter_reason": "sélectionner une raison",
"bans_list_no_bans": "Aucun ban actif",
"bans_list_select_all": "sélectionner tout",
"bans_list_unselect_all": "déslectionner tout",
"bans_list_unban": "déban sélection",
"bans_list_select_desc": "Sélectionne un ban pour effectuer des actions.",
"bans_list_header_check": "check",
"bans_list_header_ip": "ip",
"bans_list_header_reason": "raison",
"bans_list_header_ban_start": "début ban",
"bans_list_header_ban_end": "fin ban",
"bans_list_header_remain": "durée restante",
"bans_list_table_summary": "Liste des bans actuels (ip, raison, date et délai restant).",
"bans_add": "Ajouter une entrée",
"bans_add_remove_ban_desc": "Supprime le champ relié d'ajout de ban.",
"bans_add_save_bans_warning": "Les bans avec un conflit (comme la whitelist) seront ajoutés mais ignorés.",
"bans_add_header_ip": "ip",
"bans_add_header_ban_start": "début ban",
"bans_add_header_ban_end": "fin ban",
"bans_add_header_reason": "raison",
"bans_add_table_summary": "Liste des bans à ajouter (ip, raison et date).",
"custom_conf_total": "Configs total",
"custom_conf_global": "Configs globales",
"custom_conf_services": "Configs services",
"custom_conf_filter_search_path": "Rechercher par chemin",
"custom_conf_filter_search_name": "Rechercher par nom",
"custom_conf_filter_show_services_folders": "Voir les services",
"custom_conf_filter_show_path_with_conf": "Chemin .conf seulement",
"custom_conf_add_file": "Ajouter fichier",
"custom_conf_breadcrumb": "Chemin avec chaque dossier cliquable pour s'y rendre.",
"custom_conf_breadcrumb_item_desc": "Cliquer pour se rendre au chemin relié.",
"custom_conf_breadcrumb_back_desc": "Aller au dossier parent.",
"custom_conf_modal_title": "{action} fichier",
"custom_conf_modal_placeholder": "nom du fichier",
"custom_conf_modal_path_desc": "Montre le chemin entier avec un input avec le nom du fichier conf.",
"custom_conf_modal_editor_desc": "Remplir avec le script qui doit s'exécuter pour ce fichier.",
"custom_conf_dot_conf": ".conf",
"custom_conf_path": "Accéder à l'intérieur du dossier pour voir les fichiers enfants.",
"custom_conf_dropdown_action": "Affiche les actions possibles sur l'élément.",
"global_conf_select_plugin": "Sélectionner un plugin",
"global_conf_select_plugin_placeholder": "rechercher",
"global_conf_filter_search": "rechercher",
"global_conf_filter_search_placeholder": "titre, description...",
"global_conf_filter_method": "methodes",
"jobs_total": "Total jobs",
"jobs_reload": "Total rechargés",
"jobs_success": "Total réussis",
"jobs_filter_search": "rechercher",
"jobs_filter_search_placeholder": "mot clé",
"jobs_filter_success_state": "état de réussite",
"jobs_filter_reload_state": "état de rechargement",
"jobs_filter_interval": "interval",
"jobs_headers_name": "nom",
"jobs_headers_every": "interval",
"jobs_headers_history": "historique",
"jobs_headers_reload": "rechargement",
"jobs_headers_success": "réussite",
"jobs_headers_last_run": "dernier tour",
"jobs_headers_cache": "cache",
"jobs_headers_action": "action",
"jobs_state_reload_failed": "recharge échoué",
"jobs_state_reload_succeed": "recharge réussie",
"jobs_state_success_failed": "échec",
"jobs_state_success_succeed": "succès",
"jobs_actions_run": "lancer",
"jobs_actions_show_history": "Montre dans un modal l'historique des actions au clique.",
"jobs_actions_cache_download": "Télécharger le cache",
"jobs_history_title": "historique",
"jobs_history_headers_success": "réussite",
"jobs_history_headers_start_date": "début exécution",
"jobs_history_headers_end_date": "fin exécution",
"jobs_table_summary": "Liste des jobs (nom, interval, historique, rechargement, réussite, cache et lancement).",
"plugins_total": "plugins total",
"plugins_internal": "plugins internes",
"plugins_external": "plugins externes",
"plugins_filter_search": "rechercher",
"plugins_filter_search_placeholder": "mot clé",
"plugins_filter_type": "type de plugin",
"act": "liste des plugins",
"plugins_list_actions_link": "lien vers la page custom du plugin",
"plugins_list_actions_delete": "supprime le plugin relié.",
"plugins_delete_modal_title": "Supprimer le {name} ?",
"plugins_delete_modal_text": "Etes-vous sûr de vouloir supprimer le plugin {name} ?",
"plugins_page_label": "Accède à la page du plugin concerné",
"services_total": "total services",
"services_methods_count": "Total méthodes",
"services_filter_more_toggle": "Ouvrir/fermer les filtres supplémentaires.",
"services_service_search": "rechercher par nom",
"services_service_search_placeholder": "www.example.com",
"services_service_select_method": "Méthodes",
"services_service_select_bad_behavior": "Mauvais comportement",
"services_service_select_limit": "Limite requête",
"services_service_select_reverse_proxy": "Proxy inverse",
"services_service_select_modsecurity": "ModSecurity",
"services_service_select_cors": "CORS",
"services_service_select_dnsbl": "DNSBL",
"services_list_title": "Services and plugins",
"services_list_switch_warning": "Changer de service réinitialise les changements non sauvegardés du service en cours.",
"services_list_select_service": "sélectionner un service",
"services_list_select_plugin": "sélectionner un plugin",
"services_filter_search_setting": "rechercher un paramètre",
"services_filter_search_setting_placeholder": "nom, titre, description...",
"services_filter_method_setting": "Sélectionner une méthode",
"services_detail_active": "Le paramètre est actif.",
"services_detail_inactive": "Le paramètre est inactif.",
"services_detail_bad_behavior": "Mauvais comportement",
"services_detail_modsecurity": "ModSecurity",
"services_detail_limit": "Limite requête",
"services_detail_reverse_proxy": "Proxy inverse",
"services_detail_cors": "CORS",
"services_detail_dnsbl": "DNSBL",
"services_active_new": "Créer un nouveau service",
"services_active_clone": "Créer un nouveau service (clone)",
"services_active_delete": "Supprime le service actif {name}",
"services_active_base": "service {name}",
"services_actions_new": "Nouveau service",
"services_actions_warning": "Un nom de serveur valide et disponible et/ou un changement de paramètre pour sauvegarder.",
"services_delete_title": "Supprimer un service",
"services_delete_msg": "Etes-vous sûr de vouloir supprimer le service {name} ?",
"services_redirect_desc": "redirection vers le site du service ou autre contenu http",
"services_edit_desc": "ouvrir un modal pour éditer le service.",
"services_delete_desc": "Ouvrir un modal pour supprimer le service.",
"services_clone_desc": "Créer un nouveau service basé sur les paramètres de celui-ci.",
"reporting_total": "Total rapports",
"reporting_country": "Total pays",
"reporting_reason": "Total raisons",
"reporting_filter_search": "Recherche",
"reporting_filter_search_placeholder": "url, agent utilisateur, data",
"reporting_filter_method": "Méthode",
"reporting_filter_country": "Pays",
"reporting_filter_status": "Code",
"reporting_filter_reason": "Raison",
"reporting_header_date": "Date",
"reporting_header_ip": "IP",
"reporting_header_country": "Pays",
"reporting_header_method": "Méthode",
"reporting_header_url": "URL",
"reporting_header_code": "Code",
"reporting_header_user_agent": "Agent utilisateur",
"reporting_header_reason": "Raison",
"reporting_header_data": "Data",
"reporting_table_summary": "Liste des rapports (date, ip, pays, méthode, url, code, agent utilisateur, raison, data).",
"account_settings": "Paramètres de compte",
"account_tabs_username": "Nom d'utilisateur",
"account_tabs_password": "Mot de passe",
"account_tabs_totp": "TOTP",
"account_password": "Mot de passe",
"account_password_new": "Nouveau mot de passe",
"account_password_confirm": "Confirmer nouveau mot de passe",
"account_totp_qr_code": "TOTP QR code",
"account_totp_secret": "TOTP clé secrète",
"account_totp_code": "TOTP code",
"account_totp_password": "TOTP code",
"account_username": "Nom d'utilisateur",
"account_password_placeholder": "P@ssw0rd",
"account_username_placeholder": "martin.dupont",
"account_totp_code_placeholder": "123456",
"account_totp_secret_placeholder": "clé secrète",
"inp_select_default_desc": "Relié à un composant select custom. Ne pas utiliser directement.",
"inp_select_dropdown_button_desc": "Bouton toggle de dropdown custom.",
"inp_select_label_empty": "Vide",
"inp_input_password_desc": "Toggle l'input pour montrer/cacher une donnée de type mot de passe.",
"inp_input_clipboard_desc": "Copie la valeur dans le presse-papier.",
"inp_upload_add": "cliquez ou glissez-déposez",
"inp_upload_warning": "Les fichiers upload sont exécutés directement.",
"inp_upload_state_upload": "upload en cours",
"inp_upload_state_fail": "upload ratée",
"inp_upload_state_success": "upload réussie"
}

View file

@ -0,0 +1,47 @@
<script setup>
import { reactive, onBeforeMount } from "vue";
import Builder from "@components/Builder.vue";
// Define reactive properties
const data = reactive({
// Define properties here
title : 'No title'
})
// Retrieve default or flask data if available
onBeforeMount(() => {
const dataEl = document.querySelector('[data-flask]');
data.title = dataEl.getAttribute('data-flask') && dataEl.getAttribute('data-flask') !== "{{ flask_data }}" ? dataEl.getAttribute('data-flask') : dataEl.getAttribute('data-default-value');
})
// Example of builder
const builder = [{
// we are starting with the top level container name
// this can be a "card", "modal", "table"... etc
"type": "card",
"containerClass": "", // tailwind css grid class (items-start, ...)
"containerColumns" : {"pc": 12, "tablet": 12, "mobile": 12},
// container title
"title" : "My awesome card",
// Each widget need a name (here type) and associated data
// We need to send specific data for each widget type
widgets: [
{
type : "Checkbox",
data : {containerClass : "", columns : {"pc": 6, "tablet": 12, "mobile": 12}, id:"test-check", value: "yes", label: "Checkbox", name: "checkbox", required: true, version: "v1.0.0", hideLabel: false, headerClass: "" }
}, {
type : "Select",
data : {containerClass : "", columns : {"pc": 6, "tablet": 12, "mobile": 12}, id: 'test-select', value: 'yes', values: ['yes', 'no'], name: 'test-select', disabled: false, required: true, label: 'Test select', tabId: '1',}
}
]
},
]
</script>
<template>
<div class="bg-secondary flex flex-col items-center justify-center h-full">
<div style="width: 600px;">
<Builder :builder="builder" />
</div>
</div>
</template>

View file

@ -0,0 +1,11 @@
import { createApp } from "vue";
import { createPinia } from "pinia";
import { getI18n } from "@utils/lang.js";
import Builder from "./Builder.vue";
const pinia = createPinia();
createApp(Builder)
.use(pinia)
.use(getI18n(["dashboard", "api", "action", "bans", "inp"]))
.mount("#app");

View file

@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/images/favicon.ico" />
<link rel="stylesheet" href="/css/style.css" />
<link rel="stylesheet" href="/css/flag-icons.min.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BunkerWeb | BUILDER</title>
</head>
<body>
<div data-default-value="Title default !" data-flask="{{ flask_data }}" class="hidden"></div>
<div id="app"></div>
<script type="module" src="builder.js"></script>
</body>
</html>

View file

@ -1,44 +1,55 @@
<script setup>
import { reactive, onBeforeMount } from "vue";
import { reactive, onBeforeMount, triggerRef } from "vue";
import Checkbox from "@components/Forms/Field/Checkbox.vue";
import Select from "@components/Forms/Field/Select.vue";
import Input from "@components/Forms/Field/Input.vue";
import Datepicker from "@components/Forms/Field/Datepicker.vue";
import Button from "@components/Widget/Button.vue";
import Builder from "@components/Builder.vue";
// Define reactive properties
const data = reactive({
// Define properties here
title : 'No title'
})
// Retrieve default or flask data if available
onBeforeMount(() => {
const dataEl = document.querySelector('[data-flask]');
data.title = dataEl.getAttribute('data-flask') && dataEl.getAttribute('data-flask') !== "{{ flask_data }}" ? dataEl.getAttribute('data-flask') : dataEl.getAttribute('data-default-value');
})
// Example of builder
const builder = [{
// we are starting with the top level container name
// this can be a "card", "modal", "table"... etc
"type": "card",
"containerClass": "", // tailwind css grid class (items-start, ...)
"containerColumns" : {"pc": 12, "tablet": 12, "mobile": 12},
// container title
"title" : "My awesome card",
// Each widget need a name (here type) and associated data
// We need to send specific data for each widget type
widgets: [
{
type : "Checkbox",
data : {containerClass : "", columns : {"pc": 6, "tablet": 12, "mobile": 12}, id:"test-check", value: "yes", label: "Checkbox", name: "checkbox", required: true, version: "v1.0.0", hideLabel: false, headerClass: "text-red-500" }
}, {
type : "Select",
data : {containerClass : "", columns : {"pc": 6, "tablet": 12, "mobile": 12}, id: 'test-select', value: 'yes', values: ['yes', 'no'], name: 'test-select', disabled: false, required: true, label: 'Test select', tabId: '1',}
}
]
},
]
const checkboxData = {
id: 'test-checkbox',
value: 'yes',
name: 'test-checkbox',
disabled: false,
required: true,
label: 'Test checkbox',
tabId: '1',
}
const selectData = {
id: 'test-select',
value: 'yes',
values: ['yes', 'no'],
name: 'test-select',
disabled: false,
required: true,
requiredValues : ['no'],
label: 'Test select',
tabId: '1',
}
const inputData = {
id: 'test-input',
value: 'yes',
type: "text",
name: 'test-input',
disabled: false,
required: true,
label: 'Test input',
pattern : "(test)",
tabId: '1',
}
const datepickerData = {
id: 'test-datepicker',
name: 'test-datepicker',
disabled: false,
required: true,
label: 'Test datepicker',
tabId: '1',
}
const buttonData = {
id: 'test-button',
@ -48,15 +59,42 @@ const buttonData = {
eventAttr: {"store" : "modal", "default" : "close", "value" : "open", "target" : "modal_id", "valueExpanded" : "open"},
columns: {"pc": 12, "tablet": 12, "mobile": 12},
tabId: '1',
}
const buttonSVGData = {
id: 'test-button',
text: 'Test button',
type: 'button',
disabled: false,
eventAttr: {"store" : "modal", "default" : "close", "value" : "open", "target" : "modal_id", "valueExpanded" : "open"},
columns: {"pc": 12, "tablet": 12, "mobile": 12},
tabId: '1',
iconName : "add"
}
const buttonOnlySVGData = {
id: 'test-button',
text: 'Test button',
hideText : true,
type: 'button',
disabled: false,
eventAttr: {"store" : "modal", "default" : "close", "value" : "open", "target" : "modal_id", "valueExpanded" : "open"},
columns: {"pc": 12, "tablet": 12, "mobile": 12},
tabId: '1',
iconName : "add"
}
</script>
<template>
<div class="bg-secondary flex flex-col items-center justify-center h-full">
<div style="width: 300px;">
<Checkbox v-bind="checkboxData" />
<Select v-bind="selectData" />
<Input v-bind="inputData" />
<Datepicker v-bind="datepickerData" />
<Button v-bind="buttonData" />
<Builder :builder="builder" />
<Button v-bind="buttonSVGData" />
<Button v-bind="buttonOnlySVGData" />
</div>
</div>
</template>

View file

@ -10,7 +10,6 @@ export const useEventStore = defineStore("event", () => {
// add only if the event is not already in the store
function addEvent(name, value) {
console.log(event.value)
if (!(name in event.value)) event.value[name] = value;
}

View file

@ -1,12 +1,11 @@
import { createI18n } from "vue-i18n";
import fr from "@lang/fr.json" assert { type: "json" };
import en from "@lang/en.json" assert { type: "json" };
const availablesLangs = ["en", "fr"];
const availablesLangs = ["en"];
function getAllLang() {
return { fr: fr, en: en };
return { en: en };
}
function getAllLangCurrPage(pagesArr) {