Page MenuHomeSealhub

No OneTemporary

diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 73bbdb3..7df9ee9 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -1,48 +1,49 @@
module.exports = {
env: { node: true },
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "prettier"],
extends: [
"eslint:recommended",
// disabled due to https://github.com/typescript-eslint/typescript-eslint/issues/8804
// "plugin:@typescript-eslint/recommended",
// disabled due to https://github.com/typescript-eslint/typescript-eslint/issues/8804
// "plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:prettier/recommended",
],
parserOptions: {
sourceType: "module",
ecmaFeatures: {
modules: true,
},
// disabled due to https://github.com/typescript-eslint/typescript-eslint/issues/8804
//project: ["./tsconfig.json", "./tsconfig-back.json"],
},
rules: {
"@typescript-eslint/no-unused-vars": [2, { varsIgnorePattern: "TempstreamJSX" }],
+ "no-unused-vars": [2, { varsIgnorePattern: "TempstreamJSX" }],
"@typescript-eslint/require-await": 0,
/* "jsdoc/require-description": 2, */
"no-await-in-loop": 2,
"@typescript-eslint/consistent-type-assertions": [1, { assertionStyle: "never" }],
"no-console": [1, { allow: ["error"] }],
},
ignorePatterns: ["dist/*", "public/dist/*", "coverage/*", "webhint/*"],
settings: { jsdoc: { mode: "typescript" } },
overrides: [
{
files: ["*.subtest.ts", "*.test.ts"],
rules: {
"@typescript-eslint/no-unsafe-member-access": 0,
"prefer-const": 0,
"@typescript-eslint/no-unsafe-call": 0,
"@typescript-eslint/no-unsafe-return": 0,
"@typescript-eslint/no-unsafe-assignment": 0,
"no-await-in-loop": 1, // sometimes it's easier to debug when requests run sequentially
},
},
{
files: ["*.stimulus.ts", "src/front/*.ts"],
env: { browser: true },
},
],
};
diff --git a/.hintrc b/.hintrc
index 29b634a..593bc8e 100644
--- a/.hintrc
+++ b/.hintrc
@@ -1,50 +1,50 @@
{
"connector": {
"name": "jsdom"
},
"formatters": ["codeframe"],
"hintsTimeout": 20000,
"extends": ["web-recommended", "accessibility"],
"hints": {
"no-friendly-error-pages": "off",
"no-broken-links": "warning",
"doctype": "error",
"apple-touch-icons": "error",
"button-type": "error",
- "compat-api/css": "error",
+ "compat-api/css": "warning",
"compat-api/html": [
"error",
{
"ignore": ["img[loading]"]
}
],
"create-element-svg": "error",
"css-prefix-order": "error",
"disown-opener": "error",
"highest-available-document-mode": "error",
"leading-dot-classlist": "error",
"manifest-exists": "error",
"meta-charset-utf-8": "error",
"meta-viewport": "error",
"no-bom": "error",
"no-inline-styles": "error",
"no-protocol-relative-urls": "error",
"html-checker": "error",
"scoped-svg-styles": "error",
"sri": "error",
"axe/aria": "error",
"axe/color": "error",
"axe/forms": "error",
"axe/keyboard": "error",
"axe/language": "error",
"axe/name-role-value": "error",
"axe/parsing": "error",
"axe/semantics": "error",
"axe/sensory-and-visual-cues": "error",
"axe/structure": "error",
"axe/tables": "error",
"axe/text-alternatives": "error",
"axe/time-and-media": "error",
"no-vulnerable-javascript-libraries": "off"
}
}
diff --git a/src/back/jdd-components/autoscrolling-images/autoscrolling-images-arrow.svg b/src/back/jdd-components/autoscrolling-images/autoscrolling-images-arrow.svg
new file mode 100644
index 0000000..03dd402
--- /dev/null
+++ b/src/back/jdd-components/autoscrolling-images/autoscrolling-images-arrow.svg
@@ -0,0 +1,3 @@
+<svg width="32" height="12" viewBox="0 0 32 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1 5.25C0.585786 5.25 0.25 5.58579 0.25 6C0.25 6.41421 0.585786 6.75 1 6.75V5.25ZM31.5303 6.53033C31.8232 6.23744 31.8232 5.76256 31.5303 5.46967L26.7574 0.696699C26.4645 0.403806 25.9896 0.403806 25.6967 0.696699C25.4038 0.989593 25.4038 1.46447 25.6967 1.75736L29.9393 6L25.6967 10.2426C25.4038 10.5355 25.4038 11.0104 25.6967 11.3033C25.9896 11.5962 26.4645 11.5962 26.7574 11.3033L31.5303 6.53033ZM1 6.75H31V5.25H1V6.75Z" fill="#0D4D69"/>
+</svg>
diff --git a/src/back/jdd-components/autoscrolling-images/autoscrolling-images.css b/src/back/jdd-components/autoscrolling-images/autoscrolling-images.css
new file mode 100644
index 0000000..87438cd
--- /dev/null
+++ b/src/back/jdd-components/autoscrolling-images/autoscrolling-images.css
@@ -0,0 +1,177 @@
+.autoscrolling-images {
+ display: flex;
+ justify-content: center;
+}
+
+.autoscrolling-images-wrapper {
+ display: grid;
+ gap: 24px;
+}
+
+.autoscrolling-images__title-wrapper {
+ max-width: 940px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+}
+
+.autoscrolling-images__title {
+ font-size: 32px;
+ color: #0d4d69;
+ margin: 0;
+}
+
+.autoscrolling-images__arrow-carousel-container {
+ position: absolute;
+ top: -51px;
+ right: -90px;
+ width: 92px;
+ overflow-x: hidden;
+}
+
+.autoscrolling-images__arrow-carousel {
+ transition: none !important;
+ width: 100%;
+ display: flex;
+ flex-flow: row nowrap;
+}
+
+.autoscrolling-images__arrow-container {
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ flex-wrap: wrap;
+ scroll-snap-align: start;
+ flex: 1 0 100%;
+}
+
+.autoscrolling-images__arrow img {
+ max-width: 30px;
+}
+
+.autoscrolling-images__arrow:hover {
+ cursor: pointer;
+}
+
+.autoscrolling-images__img-arrow-left {
+ transform: rotate(180deg);
+}
+
+.autoscrolling-images__carousel-container {
+ position: relative;
+ max-width: 940px;
+}
+
+.autoscrolling-images__imgs-carousel {
+ overflow-x: clip;
+}
+
+.autoscrolling-images__carousel {
+ width: 100%;
+ display: flex;
+ flex-flow: row nowrap;
+}
+
+.autoscrolling-images__carousel-page {
+ align-items: center;
+ scroll-snap-align: start;
+ box-sizing: border-box;
+
+ flex: 1 0 100%;
+
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-evenly;
+
+ max-width: 940px;
+}
+
+.autoscrolling-images__img-wrapper {
+ width: 288px;
+ height: 150px;
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+}
+
+.autoscrolling-images__radio {
+ display: none;
+}
+
+.autoscrolling-images__dots-container {
+ display: flex;
+ justify-content: center;
+ margin-top: 24px;
+}
+
+.autoscrolling-images__dots {
+ cursor: pointer;
+ height: 12px;
+ width: 12px;
+ background-color: #cadae4;
+ border-radius: 50%;
+ display: inline-block;
+ margin: 4px;
+}
+
+.autoscrolling-images__dots:hover {
+ background-color: #0d4d69;
+}
+
+@keyframes autoscrolling-images-infiniteScroll {
+ 0% {
+ transform: translateX(0%);
+ }
+ 50% {
+ transform: translateX(calc(-100% + 100cqw));
+ }
+ 100% {
+ transform: translateX(0%);
+ }
+}
+
+@container (width < 1115px) {
+ .autoscrolling-images__arrow-carousel-container {
+ right: 0;
+ }
+}
+
+@container (width < 800px) {
+ .autoscrolling-images__arrow-carousel-container {
+ display: none;
+ }
+
+ .autoscrolling-images__dots-container {
+ display: none;
+ }
+
+ .autoscrolling-images__carousel {
+ max-width: none;
+ width: max-content;
+ }
+
+ .autoscrolling-images__carousel-container {
+ margin: 0;
+ max-width: calc(100cqw - 20px);
+ }
+
+ .autoscrolling-images__carousel-page {
+ display: flex;
+ flex: none !important;
+ margin: 0;
+ flex-wrap: nowrap !important;
+ max-width: none;
+ }
+
+ .autoscrolling-images__img-wrapper {
+ min-width: 288px;
+ }
+
+ .autoscrolling-images__carousel {
+ animation-name: autoscrolling-images-infiniteScroll;
+ animation-duration: var(--animation-length);
+ animation-iteration-count: infinite;
+ animation-timing-function: ease-in-out;
+ }
+}
diff --git a/src/back/jdd-components/autoscrolling-images/autoscrolling-images.jdd.tsx b/src/back/jdd-components/autoscrolling-images/autoscrolling-images.jdd.tsx
new file mode 100644
index 0000000..bce8bef
--- /dev/null
+++ b/src/back/jdd-components/autoscrolling-images/autoscrolling-images.jdd.tsx
@@ -0,0 +1,164 @@
+import arrow from "./autoscrolling-images-arrow.svg";
+
+import { FlatTemplatable, TempstreamJSX } from "tempstream";
+import {
+ Component,
+ ComponentArguments,
+ ExtractStructuredComponentArgumentsValues,
+ JDDContext,
+} from "@sealcode/jdd";
+
+const component_arguments = {
+ title: new ComponentArguments.ShortText(),
+ interval: new ComponentArguments.ShortText().setExampleValues(["5"]),
+ imagesPerPage: new ComponentArguments.ShortText().setExampleValues(["6"]),
+ images: new ComponentArguments.List(
+ new ComponentArguments.Structured({
+ image: new ComponentArguments.Image(),
+ alt: new ComponentArguments.ShortText(),
+ })
+ ),
+} as const;
+
+export class AutoscrollingImages extends Component<typeof component_arguments> {
+ getArguments() {
+ return component_arguments;
+ }
+
+ toHTML(
+ {
+ title,
+ interval,
+ imagesPerPage,
+ images,
+ }: ExtractStructuredComponentArgumentsValues<typeof component_arguments>,
+ { render_image }: JDDContext
+ ): FlatTemplatable {
+ const imageNumberPerPage = parseInt(imagesPerPage);
+ let parsedImagesArray = [];
+
+ for (let i = 0; i < images.length; i += imageNumberPerPage) {
+ parsedImagesArray.push(images.slice(i, i + imageNumberPerPage));
+ }
+
+ const radioButtonIdPrefix = "r" + Math.floor(100 + Math.random() * 900);
+ const numberOfImages = images.length * 5;
+ const titleUpperCase = title.toUpperCase();
+
+ return (
+ <div
+ class="autoscrolling-images"
+ data-controller="autoscrolling-images"
+ data-autoscrolling-images-interval={interval}
+ >
+ <style>
+ {parsedImagesArray
+ .map(
+ (_, pageIndex) =>
+ `#${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}:checked ~ .autoscrolling-images__imgs-carousel > .autoscrolling-images__carousel {
+ transform: translateX(calc(${pageIndex} * (-100%)));
+ }
+
+ #${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}:checked ~ .autoscrolling-images__arrow-carousel-container
+ > .autoscrolling-images__arrow-carousel {
+ transform: translateX(calc(${pageIndex} * (-100%)));
+
+ }
+
+ #${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}:checked ~ .autoscrolling-images__dots-container
+ > label:nth-child(${pageIndex + 1}) {
+ background-color: #0d4d69;
+
+ }`
+ )
+ .join("\n")}
+ </style>
+
+ <div
+ class="autoscrolling-images-wrapper"
+ data-carousel-id-prefix={radioButtonIdPrefix}
+ >
+ <div class="autoscrolling-images__title-wrapper">
+ <h2 class="autoscrolling-images__title">{titleUpperCase}</h2>
+ </div>
+
+ <div class="autoscrolling-images__carousel-container">
+ {parsedImagesArray.map((_, pageIndex) => (
+ <input
+ class="autoscrolling-images__radio"
+ type="radio"
+ name="autoscrolling-images__radio"
+ value={pageIndex}
+ id={`${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}`}
+ checked={pageIndex === 0}
+ data-action="autoscrolling-images#handleRadiochange"
+ />
+ ))}
+ <div class="autoscrolling-images__arrow-carousel-container">
+ <div class="autoscrolling-images__arrow-carousel">
+ {parsedImagesArray.map((_, pageIndex) => (
+ <div class="autoscrolling-images__arrow-container">
+ <label
+ for={`${radioButtonIdPrefix}-autoscrolling-images__radio-${
+ pageIndex == 0
+ ? parsedImagesArray.length - 1
+ : pageIndex - 1
+ }`}
+ class="autoscrolling-images__arrow"
+ >
+ <img
+ class="autoscrolling-images__img-arrow-left"
+ src={arrow.url}
+ />
+ </label>
+ <label
+ for={`${radioButtonIdPrefix}-autoscrolling-images__radio-${
+ pageIndex == parsedImagesArray.length - 1
+ ? 0
+ : pageIndex + 1
+ }`}
+ class="autoscrolling-images__arrow"
+ >
+ <img src={arrow.url} />
+ </label>
+ </div>
+ ))}
+ </div>
+ </div>
+ <div class="autoscrolling-images__imgs-carousel">
+ <div
+ class="autoscrolling-images__carousel"
+ style={`--animation-length: ${numberOfImages}s`}
+ >
+ {parsedImagesArray.map((page) => (
+ <div class="autoscrolling-images__carousel-page">
+ {page.map((image) => (
+ <div class="autoscrolling-images__img-wrapper">
+ {render_image(image.image, {
+ container: {
+ width: 288,
+ height: 150,
+ objectFit: "contain",
+ },
+ alt: image.alt,
+ })}
+ </div>
+ ))}
+ </div>
+ ))}
+ </div>
+ </div>
+ <div class="autoscrolling-images__dots-container">
+ {parsedImagesArray.map((pageIndex) => (
+ <label
+ for={`${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}`}
+ class="autoscrolling-images__dots"
+ ></label>
+ ))}
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
diff --git a/src/back/jdd-components/autoscrolling-images/autoscrolling-images.stimulus.ts b/src/back/jdd-components/autoscrolling-images/autoscrolling-images.stimulus.ts
new file mode 100644
index 0000000..d4b1934
--- /dev/null
+++ b/src/back/jdd-components/autoscrolling-images/autoscrolling-images.stimulus.ts
@@ -0,0 +1,67 @@
+import { Controller } from "stimulus";
+
+export default class AutoscrollingImages extends Controller {
+ currentIndex = 0;
+ interval_id: number;
+
+ getInterval(): number {
+ return parseInt(
+ this.element.getAttribute("data-autoscrolling-images-interval") || "5"
+ );
+ }
+
+ getRadioButtons(): Array<HTMLInputElement> {
+ return Array.from(this.element.querySelectorAll(".autoscrolling-images__radio"));
+ }
+
+ handleRadioChange() {
+ const selectedRadio = this.getRadioButtons().findIndex(
+ (radio: HTMLInputElement) => radio.checked
+ );
+ this.currentIndex = selectedRadio !== -1 ? selectedRadio : 0;
+ }
+
+ async connect() {
+ this.currentIndex = 0;
+
+ let intervalTime: number;
+ const interval = this.getInterval();
+ if (!interval) {
+ intervalTime = interval * 1000;
+ } else {
+ intervalTime = 5000;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ this.interval_id = setInterval(
+ () => this.next_slide(),
+ intervalTime
+ ) as unknown as number;
+ }
+
+ async disconnect() {
+ clearInterval(this.interval_id);
+ }
+
+ next_slide() {
+ const carouselPages = this.element.querySelectorAll(
+ ".autoscrolling-images__carousel-page"
+ );
+
+ const radioButtonIdPrefix = this.element
+ .querySelector(".autoscrolling-images-wrapper")
+ .getAttribute("data-carousel-id-prefix");
+
+ const nextIndex = (this.currentIndex + 1) % carouselPages.length;
+
+ const nextButton =
+ radioButtonIdPrefix + "-autoscrolling-images__radio-" + nextIndex;
+
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
+ (document.getElementById(nextButton) as HTMLInputElement).checked = true;
+
+ this.currentIndex = nextIndex;
+
+ // this.handleRadioChange();
+ }
+}
diff --git a/src/back/jdd-components/components.ts b/src/back/jdd-components/components.ts
index 647173c..3d8516d 100644
--- a/src/back/jdd-components/components.ts
+++ b/src/back/jdd-components/components.ts
@@ -1,16 +1,19 @@
// DO NOT EDIT! This file is generated automaticaly with 'npm run generate-components'
import { Registry } from "@sealcode/jdd";
export const registry = new Registry();
+import { AutoscrollingImages } from "./autoscrolling-images/autoscrolling-images.jdd.js";
+registry.add("autoscrolling-images", AutoscrollingImages);
+
import { ImageDemo } from "./image-demo/image-demo.jdd.js";
registry.add("image-demo", ImageDemo);
import { MapWithPins } from "./map-with-pins/map-with-pins.jdd.js";
registry.add("map-with-pins", MapWithPins);
import { NiceBox } from "./nice-box/nice-box.jdd.js";
registry.add("nice-box", NiceBox);
import { Table } from "./table/table.jdd.js";
registry.add("table", Table);
diff --git a/src/back/routes/components.css b/src/back/routes/components.css
index c19070c..d6389de 100644
--- a/src/back/routes/components.css
+++ b/src/back/routes/components.css
@@ -1,92 +1,93 @@
.title--components {
body {
max-width: none;
}
.two-column {
display: grid;
grid-template-columns: 1fr 15px min-content;
}
.resize-gutter {
background-color: gray;
cursor: ew-resize;
height: 100%;
}
.resizable {
overflow-x: auto;
}
transition: transform 200ms, opacity 200ms;
&.restarting {
transform: scale(0.99);
opacity: 0.6;
}
.component-preview {
width: var(--resizable-column-width);
& > fieldset {
min-width: 0; /* default is min-content and that causes overflow*/
max-height: calc(100vh - 75px);
overflow-x: auto;
}
}
.component-arguments {
max-height: calc(100vh - 80px);
overflow-y: auto;
}
}
.component-preview-parameters {
fieldset {
background-color: #80808024;
table {
td,
th {
outline: 0.5px solid #0000006b;
&.subdued > * {
opacity: 50%;
}
&.subdued:hover > * {
opacity: 100%;
}
&.sticky {
position: sticky;
background-color: #ececec;
}
&.sticky--left {
left: 0;
box-shadow: 5px 0px 10px -4px #00000047;
}
&.sticky--top {
top: 0;
box-shadow: 0px 5px 10px -4px #00000047;
}
}
}
}
}
.component-preview {
* {
transition: all 150ms;
}
+ container-type: inline-size;
}
@media (scripting: none) {
body {
min-width: max-content;
}
}
.component-preview-size-select {
margin-left: 10px;
}
diff --git a/src/front/controllers.ts b/src/front/controllers.ts
index 900e884..07343c1 100644
--- a/src/front/controllers.ts
+++ b/src/front/controllers.ts
@@ -1,22 +1,25 @@
// DO NOT EDIT! This file is generated automaticaly with 'npm run generate-stimulus'
import * as Turbo from "@hotwired/turbo";
import { Application } from "stimulus";
const application = Application.start();
import { default as RefreshOnTsChanges } from "./../back/html-controllers/refresh-on-ts-changes.stimulus.js";
application.register("refresh-on-ts-changes", RefreshOnTsChanges);
import { default as RefreshStyles } from "./../back/html-controllers/refresh-styles.stimulus.js";
application.register("refresh-styles", RefreshStyles);
+import { default as AutoscrollingImages } from "./../back/jdd-components/autoscrolling-images/autoscrolling-images.stimulus.js";
+application.register("autoscrolling-images", AutoscrollingImages);
+
import { default as MapWithPins } from "./../back/jdd-components/map-with-pins/map-with-pins.stimulus.js";
application.register("map-with-pins", MapWithPins);
import { default as ComponentDebugger } from "./../back/routes/component-preview/component-debugger.stimulus.js";
application.register("component-debugger", ComponentDebugger);
import { default as InputImagePreview } from "./../back/routes/component-preview/input-image-preview.stimulus.js";
application.register("input-image-preview", InputImagePreview);
export { Turbo };
diff --git a/src/includes.css b/src/includes.css
index 711a57f..f1031be 100644
--- a/src/includes.css
+++ b/src/includes.css
@@ -1,11 +1,12 @@
/* DO NOT EDIT! This file is generated automaticaly with npx sealgen generate-css-includes */
@import "../node_modules/@sealcode/sealgen/src/forms/forms.css";
+@import "back/jdd-components/autoscrolling-images/autoscrolling-images.css";
@import "back/jdd-components/image-demo/image-demo.css";
@import "back/jdd-components/map-with-pins/map-with-pins.css";
@import "back/jdd-components/nice-box/nice-box.css";
@import "back/jdd-components/table/table.css";
@import "back/routes/common/ui/input.css";
@import "back/routes/components.css";
@import "colors.css";
@import "tables.css";

File Metadata

Mime Type
text/x-diff
Expires
Sat, Nov 8, 14:49 (4 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1032837
Default Alt Text
(19 KB)

Event Timeline