diff --git a/.eleventy.js b/.eleventy.js index 98082aa..00dded1 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -1,6 +1,14 @@ module.exports = function (eleventyConfig) { // eleventyConfig.addPlugin(EleventyHtmlBasePlugin); + eleventyConfig.setLiquidOptions({ + // greedy: false, + // trimOutputLeft: true, + // trimOutputRight: true, + // trimTagLeft: true, + // trimTagRight : true, + }); + eleventyConfig.setNunjucksEnvironmentOptions({ // throwOnUndefined: true, trimBlocks: true @@ -32,6 +40,10 @@ module.exports = function (eleventyConfig) { eleventyConfig.addPassthroughCopy("vendor"); eleventyConfig.addPassthroughCopy({"node_modules/bootstrap-icons": "vendor/bootstrap-icons"}); + eleventyConfig.addPassthroughCopy({ + "node_modules/jquery/dist/jquery.min.js": "vendor", + "node_modules/jquery/dist/jquery.min.map": "vendor" + }); // eleventyConfig.addPassthroughCopy({"node_modules/normalize.css/normalize.css": "vendor/normalize.css"}); eleventyConfig.addWatchTarget("./source/style/"); @@ -43,9 +55,7 @@ module.exports = function (eleventyConfig) { includes: "../templates", data: "../data" }, - markdownTemplateEngine: "njk", - htmlTemplateEngine: "njk", - templateFormats: ["html", "njk", "md"], + templateFormats: ["html", "liquid", "njk", "md"] // pathPrefix: './demo/' - } + }; }; diff --git a/package-lock.json b/package-lock.json index 73baa18..1fc8cd0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@11ty/eleventy": "^2.0.1", "bootstrap-icons": "^1.13.1", + "jquery": "^3.7.1", "sass": "^1.93.0" }, "devDependencies": { @@ -1583,6 +1584,12 @@ "node": ">=10" } }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "license": "MIT" + }, "node_modules/js-stringify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", diff --git a/package.json b/package.json index d2759a8..3dc6f91 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "dependencies": { "@11ty/eleventy": "^2.0.1", "bootstrap-icons": "^1.13.1", + "jquery": "^3.7.1", "sass": "^1.93.0" } -} \ No newline at end of file +} diff --git a/source/code/_ui.js b/source/code/drag.js similarity index 100% rename from source/code/_ui.js rename to source/code/drag.js diff --git a/source/code/_intro.js b/source/code/intro.js similarity index 100% rename from source/code/_intro.js rename to source/code/intro.js diff --git a/source/code/windows.js b/source/code/windows.js new file mode 100644 index 0000000..f282729 --- /dev/null +++ b/source/code/windows.js @@ -0,0 +1,280 @@ +class Draggable { + constructor(element) { + this.element = element; + this.offsetX = 0; + this.offsetY = 0; + this.isDragging = false; + this.barSize = ''; + + this.init(); + } + + init() { + this.element.addEventListener('mousedown', this.onMouseDown.bind(this)); + document.addEventListener('mousemove', this.onMouseMove.bind(this)); + document.addEventListener('mouseup', this.onMouseUp.bind(this)); + this.setPosition('bottom'); + } + + onMouseDown(event) { + this.isDragging = true; + this.offsetX = event.clientX - this.element.getBoundingClientRect().left; + this.offsetY = event.clientY - this.element.getBoundingClientRect().top; + + event.preventDefault(); + } + + onMouseMove(event) { + if (!this.isDragging) { + return; + } + + let x = event.clientX - this.offsetX; + let y = event.clientY - this.offsetY; + + // Update the position of the element + this.element.style.left = `${x}px`; + this.element.style.top = `${y}px`; + } + + onMouseUp() { + if (!this.isDragging) { + return; + } + this.isDragging = false; + + this.snapToEdges(); + } + + snapToEdges() { + const rect = this.element.getBoundingClientRect(); + const windowWidth = window.innerWidth; + const windowHeight = window.innerHeight; + + // Determine the closest edge + const distances = { + left: rect.left, + right: windowWidth - rect.right, + top: rect.top, + bottom: windowHeight - rect.bottom + }; + + const closestEdge = Object.keys(distances).reduce((a, b) => distances[a] < distances[b] ? a : b); + + /*switch (closestEdge) { + case 'left': + this.element.style.left = '0px'; + this.element.style.top = `${rect.top}px`; + break; + case 'right': + this.element.style.left = `${windowWidth - rect.width}px`; + this.element.style.top = `${rect.top}px`; + break; + case 'top': + this.element.style.top = '0px'; + this.element.style.left = `${rect.left}px`; + break; + case 'bottom': + this.element.style.top = `${windowHeight - rect.height}px`; + this.element.style.left = `${rect.left}px`; + break; + }*/ + this.setPosition(closestEdge, this.barSize); + } + + setPosition(side, barSize) { + switch (side) { + case 'left': + // this.element.style.top = `${rect.top}px`; // Optional: keep vertical position + this.element.style.top = '0px'; + this.element.style.right = ''; + this.element.style.bottom = '0px'; + this.element.style.left = '0px'; + this.element.style.width = barSize; + this.element.style.height = ''; + break; + case 'right': + // this.element.style.left = `${windowWidth - rect.width}px`; + // this.element.style.top = `${rect.top}px`; // Optional: keep vertical position + this.element.style.top = '0px'; + this.element.style.right = '0px'; + this.element.style.bottom = '0px'; + this.element.style.left = ''; + this.element.style.width = barSize; + this.element.style.height = ''; + break; + case 'top': + // this.element.style.top = '0px'; + // this.element.style.left = `${rect.left}px`; // Optional: keep horizontal position + this.element.style.top = '0px'; + this.element.style.right = '0px'; + this.element.style.bottom = ''; + this.element.style.left = '0px'; + this.element.style.width = ''; + this.element.style.height = barSize; + break; + case 'bottom': + // this.element.style.top = `${windowHeight - rect.height}px`; + // this.element.style.left = `${rect.left}px`; // Optional: keep horizontal position + this.element.style.top = ''; + this.element.style.right = '0px'; + this.element.style.bottom = '0px'; + this.element.style.left = '0px'; + this.element.style.width = ''; + this.element.style.height = barSize; + break; + } + } +} + +class DragAdv { + constructor(element, placeholder) { + this.element = element; + this.placeholder = placeholder; + this.offsetX = 0; + this.offsetY = 0; + this.isDragging = false; + this.barSize = ''; + + this.init(); + } + + init() { + this.element.addEventListener('mousedown', this.onMouseDown.bind(this)); + document.addEventListener('mousemove', this.onMouseMove.bind(this)); + document.addEventListener('mouseup', this.onMouseUp.bind(this)); + this.setPosition('bottom', this.barSize); + } + + onMouseDown(event) { + if (event.button === 0) { + this.isDragging = true; + + this.showPlaceholder(); + + this.offsetX = this.placeholder.getBoundingClientRect().width / 2; + this.offsetY = this.placeholder.getBoundingClientRect().height / 2; + + let x = event.clientX - this.offsetX; + let y = event.clientY - this.offsetY; + + this.placeholder.style.left = `${x}px`; + this.placeholder.style.top = `${y}px`; + } + + event.preventDefault(); + } + + onMouseMove(event) { + if (!this.isDragging) return; + + let x = event.clientX - this.offsetX; + let y = event.clientY - this.offsetY; + + this.placeholder.style.left = `${x}px`; + this.placeholder.style.top = `${y}px`; + } + + onMouseUp() { + if (!this.isDragging) return; + this.isDragging = false; + + this.snapToEdges(); + this.hidePlaceholder(); + } + + showPlaceholder() { + this.element.style.display = 'none'; + this.placeholder.style.display = 'block'; + } + + hidePlaceholder() { + this.placeholder.style.display = 'none'; + this.element.style.display = ''; + } + + snapToEdges() { + const rect = this.placeholder.getBoundingClientRect(); + const windowWidth = window.innerWidth; + const windowHeight = window.innerHeight; + + const distances = { + left: rect.left, + right: windowWidth - rect.right, + top: rect.top, + bottom: windowHeight - rect.bottom + }; + + const closestEdge = Object.keys(distances).reduce((a, b) => distances[a] < distances[b] ? a : b); + + this.setPosition(closestEdge, this.barSize); + } + + setPosition(side, barSize) { + switch (side) { + case 'left': + // this.element.style.top = `${rect.top}px`; // Optional: keep vertical position + this.element.style.top = '0px'; + this.element.style.right = ''; + this.element.style.bottom = '0px'; + this.element.style.left = '0px'; + this.element.style.width = barSize; + this.element.style.height = ''; + break; + case 'right': + // this.element.style.left = `${windowWidth - rect.width}px`; + // this.element.style.top = `${rect.top}px`; // Optional: keep vertical position + this.element.style.top = '0px'; + this.element.style.right = '0px'; + this.element.style.bottom = '0px'; + this.element.style.left = ''; + this.element.style.width = barSize; + this.element.style.height = ''; + break; + case 'top': + // this.element.style.top = '0px'; + // this.element.style.left = `${rect.left}px`; // Optional: keep horizontal position + this.element.style.top = '0px'; + this.element.style.right = '0px'; + this.element.style.bottom = ''; + this.element.style.left = '0px'; + this.element.style.width = ''; + this.element.style.height = barSize; + break; + case 'bottom': + // this.element.style.top = `${windowHeight - rect.height}px`; + // this.element.style.left = `${rect.left}px`; // Optional: keep horizontal position + this.element.style.top = ''; + this.element.style.right = '0px'; + this.element.style.bottom = '0px'; + this.element.style.left = '0px'; + this.element.style.width = ''; + this.element.style.height = barSize; + break; + } + } +} + +class BestDrag { + #element; + + constructor(element) { + this.#setElement(element); + } + + #setElement(value) { + if (!value) { + throw new Error('No element found'); + } + this.#element = value; + this.#element.style.background = "hotpink"; + } + + get element() { + return this.#element; + } + + set element(value) { + this.#setElement(value); + } +} \ No newline at end of file diff --git a/source/screens/demo/components.njk b/source/screens/demo/components.njk index a6c1bfc..f327b4c 100644 --- a/source/screens/demo/components.njk +++ b/source/screens/demo/components.njk @@ -25,7 +25,7 @@ tags:

Telefone und größer

Nur Telefone

-

Nur Schreibtafeln hochkant

+

Nur Schreibtafeln hochkant

Schreibtafeln und größer

Schreibtafeln im Querformat

Schreibtafeln quer und größer

diff --git a/source/screens/demo/examples/game.liquid b/source/screens/demo/examples/game.liquid new file mode 100644 index 0000000..a57b17f --- /dev/null +++ b/source/screens/demo/examples/game.liquid @@ -0,0 +1,25 @@ +--- +title: Game - TFW +tags: +- demoExample +- gameExample +--- +{% assign bodyClass = "body_game" -%} +{% layout "hippie/app.liquid" %} + +{% block body %} +
+ +
+{% endblock %} \ No newline at end of file diff --git a/source/screens/demo/examples/intro.njk b/source/screens/demo/examples/intro.njk index 1358739..548cc3f 100644 --- a/source/screens/demo/examples/intro.njk +++ b/source/screens/demo/examples/intro.njk @@ -49,7 +49,7 @@ tags: {%- block script %} {{ super() }} - + + +{% endblock %} \ No newline at end of file diff --git a/source/screens/demo/examples/ui/drag.njk b/source/screens/demo/examples/ui/drag.njk deleted file mode 100755 index ecd3001..0000000 --- a/source/screens/demo/examples/ui/drag.njk +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Drag -tags: - - ui ---- -{% set pageId = page.fileSlug %} - -{% extends "hippie/_app_frame.njk" %} - -{% block body %} -
- -
-
-
-
-
- {{ io.frameHeader('title-bar') }} -
- {{ io.frameFooter('mode-bar') }} -
-
-
-{% endblock %} - -{%- block script %} - - -{% endblock %} \ No newline at end of file diff --git a/source/screens/demo/examples/ui/explorer.njk b/source/screens/demo/examples/ui/explorer.njk index 72de77a..c54ea0a 100755 --- a/source/screens/demo/examples/ui/explorer.njk +++ b/source/screens/demo/examples/ui/explorer.njk @@ -12,7 +12,7 @@ tags:
- + {{ io.statusBar() }} {{ io.frameFooter('mode-bar') }} diff --git a/source/screens/demo/examples/ui/form.liquid b/source/screens/demo/examples/ui/form.liquid new file mode 100644 index 0000000..492e191 --- /dev/null +++ b/source/screens/demo/examples/ui/form.liquid @@ -0,0 +1,56 @@ +--- +title: Form +tags: +- ui +--- +{% assign bodyClass = "body_frame" -%} +{% layout "hippie/app.liquid" %} + +{% block body %} +{% render 'hippie/partials/frame-header.liquid' %} +
+

Formulare

+ + +
+
+
+
+
a
+
b
+
c
+
+
+{% endblock %} + +{%- block script %} +{{ block.super -}} + +{% endblock %} \ No newline at end of file diff --git a/source/screens/demo/examples/ui/form.njk b/source/screens/demo/examples/ui/form.njk deleted file mode 100644 index 2e6c088..0000000 --- a/source/screens/demo/examples/ui/form.njk +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Form -tags: - - ui ---- -{% extends "hippie/_app_frame.njk" %} - -{% block body %} - {{ io.frameHeader('title-bar') }} -
-

Formulare

- - -
-
-
-
-
a
-
b
-
c
-
-
-{% endblock %} - -{%- block script %} - {{ super() }} - -{% endblock %} \ No newline at end of file diff --git a/source/screens/demo/examples/ui/gallery.liquid b/source/screens/demo/examples/ui/gallery.liquid new file mode 100755 index 0000000..f29cae5 --- /dev/null +++ b/source/screens/demo/examples/ui/gallery.liquid @@ -0,0 +1,77 @@ +--- +title: Gallery +tags: +- ui +--- +{% assign bodyClass = "body_frame" -%} +{% layout "hippie/app.liquid" %} + +{% block body %} +{% render 'hippie/partials/frame-header.liquid' %} +
+
+
+ + +
+ + {% render 'hippie/partials/frame-status.liquid' %} +
+
+{% render 'hippie/partials/frame-mode.liquid' %} +{% endblock %} + +{%- block script %} +{{ block.super -}} + +{% endblock %} \ No newline at end of file diff --git a/source/screens/demo/examples/ui/windows.liquid b/source/screens/demo/examples/ui/windows.liquid new file mode 100644 index 0000000..daacb66 --- /dev/null +++ b/source/screens/demo/examples/ui/windows.liquid @@ -0,0 +1,55 @@ +--- +title: Windows +tags: +- ui +--- +{% assign bodyClass = "body_frame" -%} +{% layout "hippie/app.liquid" %} + +{% block body %} +
+ + + +
+ + + +
+
+
+
+{% endblock %} + +{%- block script %} + + +{% endblock %} \ No newline at end of file diff --git a/source/screens/demo/pages/default.liquid b/source/screens/demo/pages/default.liquid new file mode 100644 index 0000000..026c6da --- /dev/null +++ b/source/screens/demo/pages/default.liquid @@ -0,0 +1,18 @@ +--- +title: "Default" +--- +{% assign pageBase = "../" -%} +{% assign pageId = page.fileSlug -%} +{% assign pageClass = "default" -%} +{% assign bodyClass = "default" -%} +{%- layout "hippie/default.liquid" %} + +{% block title %}{{ title }}{% endblock %} + +{% block script %} +{{ block.super -}} + +{% endblock %} \ No newline at end of file diff --git a/source/screens/demo/pages/default.njk b/source/screens/demo/pages/default.njk deleted file mode 100644 index a898098..0000000 --- a/source/screens/demo/pages/default.njk +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Default ---- -{% set pageBase = "../" %} -{% set pageId = page.fileSlug %} - -{% extends "hippie/_default.njk" %} - -{% block title %}{{ title }}{% endblock %} - -{% block head %} -{{ super() }} -{% endblock %} - -{% block body %} - -{% endblock %} - -{% block script %} -{{ super() }} -{% endblock %} diff --git a/source/screens/demo/pages/hello.md b/source/screens/demo/pages/hello.md new file mode 100644 index 0000000..09a9406 --- /dev/null +++ b/source/screens/demo/pages/hello.md @@ -0,0 +1,8 @@ +--- +title: "Hello World" +layout: hippie/world.liquid +--- + +# {{ title }} + +This is a simple example for a *screen* written in Markdown, using Liquid *templates*. \ No newline at end of file diff --git a/source/style/modules/ui/_gallery_module.scss b/source/style/modules/ui/_gallery_module.scss new file mode 100644 index 0000000..4f8a233 --- /dev/null +++ b/source/style/modules/ui/_gallery_module.scss @@ -0,0 +1,18 @@ +@use "../../hippie-style/hippie"; + +.gallery { + display: flex; + flex-wrap: wrap; + justify-content: left; + align-items: start; + gap: 10px; + background-color: hippie.$color_back_io; + + & > div { + background-color: hotpink; + aspect-ratio: 2 / 3; + width: 128px; + transition: width 0.3s ease; + } +} + diff --git a/source/style/modules/ui/_game_module.scss b/source/style/modules/ui/_game_module.scss new file mode 100644 index 0000000..7bb575e --- /dev/null +++ b/source/style/modules/ui/_game_module.scss @@ -0,0 +1,3 @@ +.body_game { + background-color: hotpink; +} \ No newline at end of file diff --git a/source/style/modules/ui/_windows_module.scss b/source/style/modules/ui/_windows_module.scss new file mode 100644 index 0000000..c7a9846 --- /dev/null +++ b/source/style/modules/ui/_windows_module.scss @@ -0,0 +1,91 @@ +@use "sass:map"; + +@use "../../hippie-style/hippie"; + +$padding_half: calc(#{hippie.$space_half} - 3px) hippie.$space_half; + +%flex-bar { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: stretch; + align-content: center; + justify-content: flex-start; + gap: hippie.$space_half hippie.$space_basic; +} + +#task-bar { + @extend %flex-bar; + z-index: map.get(hippie.$z-indexes, "content-top"); + position: fixed; + //right: 0; + //bottom: 0; + //left: 0; + border: 1px solid transparent; + padding: hippie.$space_basic; + background-color: rgba(0, 0, 0, .1); + + nav, + & > div { + @extend %flex-bar; + + &:last-child { + margin-left: auto; + } + } + + button { + @extend .button_io; + overflow: hidden; + } + + nav.small { + //font-size: .8em; + + button { + border: none; + padding: $padding_half; + + &:hover { + background-color: transparent; + } + } + } + + nav.big { + font-size: 1.5em; + + button { + border: none; + padding: 0; + + &:hover { + background-color: transparent; + } + } + } + + .clock { + text-align: end; + + &, + & > * { + line-height: 1; + } + } +} + +#screen-space { + position: relative; + height: 100%; +} + +#placeholder { + display: none; + z-index: map.get(hippie.$z-indexes, "content-top"); + position: fixed; + width: 100px; + height: 100px; + border: 2px dashed deeppink; + background-color: hotpink; +} \ No newline at end of file diff --git a/source/style/ui.scss b/source/style/ui.scss index 4a1e6c8..da6ecf7 100644 --- a/source/style/ui.scss +++ b/source/style/ui.scss @@ -9,6 +9,7 @@ @use "modules/ui/form_module"; @use "modules/ui/game_module"; @use "modules/ui/gallery_module"; +@use "modules/ui/windows_module"; $color_gui_back: hippie.$color_dark; $space_gui_half: hippie.$space_half; diff --git a/source/templates/hippie/app.liquid b/source/templates/hippie/app.liquid new file mode 100644 index 0000000..2456f20 --- /dev/null +++ b/source/templates/hippie/app.liquid @@ -0,0 +1,40 @@ +{% assign pageBase = "../../../" -%} +{% assign pageId = page.fileSlug -%} +{% assign pageClass = "html_ui" -%} +{%- layout "hippie/default.liquid" %} + +{% block title %}{{ title }}{% endblock %} + +{% block links %} +{{ block.super -}} + + +{% endblock %} + +{% block script %} +{{ block.super -}} + + + + + +{% endblock %} \ No newline at end of file diff --git a/source/templates/hippie/default.liquid b/source/templates/hippie/default.liquid new file mode 100644 index 0000000..cfd5417 --- /dev/null +++ b/source/templates/hippie/default.liquid @@ -0,0 +1,37 @@ + +{% if pageId %} +{%- capture idAttr %} id="{{ pageId }}"{% endcapture -%} +{% endif -%} +{% if pageClass %} + {%- capture classAttr %} class="{{ pageClass }}"{% endcapture -%} +{% endif -%} +{% if bodyClass %} + {%- capture bodyClassAttr %} class="{{ bodyClass }}"{% endcapture -%} +{% endif -%} + + + + {% block head %} + + {{- hippie.titlePrefix -}} + {% block title %}{% endblock -%} + {{ hippie.titlePostfix -}} + + {% block meta -%} + {% render "hippie/partials/meta.liquid" %} + {% endblock -%} + {% block links -%} + {% render "hippie/partials/links.liquid" %} + {% endblock -%} + {% endblock -%} + + + +{%- block body %}{% endblock -%} +{% block script -%} + +{% endblock -%} + + \ No newline at end of file diff --git a/source/templates/hippie/macros/_io.njk b/source/templates/hippie/macros/_io.njk index 36a3b9e..f9a7300 100644 --- a/source/templates/hippie/macros/_io.njk +++ b/source/templates/hippie/macros/_io.njk @@ -32,4 +32,18 @@ +{% endmacro %} + +{% macro statusBar(title) %} +
+ + +
{% endmacro %} \ No newline at end of file diff --git a/source/templates/hippie/partials/frame-header.liquid b/source/templates/hippie/partials/frame-header.liquid new file mode 100644 index 0000000..14d04bc --- /dev/null +++ b/source/templates/hippie/partials/frame-header.liquid @@ -0,0 +1,20 @@ +
+ + +
\ No newline at end of file diff --git a/source/templates/hippie/partials/frame-mode.liquid b/source/templates/hippie/partials/frame-mode.liquid new file mode 100644 index 0000000..4e87985 --- /dev/null +++ b/source/templates/hippie/partials/frame-mode.liquid @@ -0,0 +1,10 @@ +
+ + +
\ No newline at end of file diff --git a/source/templates/hippie/partials/frame-status.liquid b/source/templates/hippie/partials/frame-status.liquid new file mode 100644 index 0000000..98c94f9 --- /dev/null +++ b/source/templates/hippie/partials/frame-status.liquid @@ -0,0 +1,11 @@ +
+ + +
\ No newline at end of file diff --git a/source/templates/hippie/partials/links.liquid b/source/templates/hippie/partials/links.liquid new file mode 100644 index 0000000..c1a8845 --- /dev/null +++ b/source/templates/hippie/partials/links.liquid @@ -0,0 +1,3 @@ +{% comment %}{% endcomment %} + + diff --git a/source/templates/hippie/partials/meta.liquid b/source/templates/hippie/partials/meta.liquid new file mode 100644 index 0000000..fa0516e --- /dev/null +++ b/source/templates/hippie/partials/meta.liquid @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/source/templates/hippie/world.liquid b/source/templates/hippie/world.liquid new file mode 100644 index 0000000..ca935dc --- /dev/null +++ b/source/templates/hippie/world.liquid @@ -0,0 +1,11 @@ + + + + + {{ title }} + + + +{{ content }} + + \ No newline at end of file