From 4387abe52f88fa29604f3fd6e974e2dd537ede58 Mon Sep 17 00:00:00 2001 From: Spedon <70063177+Sped0n@users.noreply.github.com> Date: Sun, 29 Oct 2023 12:39:56 +0800 Subject: [PATCH 01/13] Gsap (#120) * feat: add gsap to deps * chore: migrate to pnpm * refractor: change var name * chore(.idea): remove unnecessary files and configurations Remove the following files and configurations from the .idea directory: - .gitignore: Remove default ignored files. - bridget.iml: Remove module file. - codeStyles/Project.xml: Remove project code style configuration. - codeStyles/codeStyleConfig.xml: Remove project code style configuration. - inspectionProfiles/Project_Default.xml: Remove project inspection profile. - jsLibraryMappings.xml: Remove JavaScript library mappings. - jsLinters/eslint.xml: Remove ESLint configuration. - modules.xml: Remove project module configuration. - vcs.xml: Remove VCS directory mapping. - watcherTasks.xml: Remove project tasks options. * chore(.prettierrc.json): update Prettier configuration to include support for go-template files and improve code formatting settings The Prettier configuration file (.prettierrc.json) has been updated with the following changes: - `useTabs` is set to `false` to use spaces for indentation - `tabWidth` is set to `2` to specify the number of spaces for each indentation level - `printWidth` is set to `88` to limit the line length to 88 characters - `singleQuote` is set to `true` to use single quotes for strings - `trailingComma` is set to `none` to remove trailing commas in arrays and objects - `bracketSpacing` is set to `true` to add spaces inside brackets - `semi` is set to `false` to remove semicolons at the end of statements - `plugins` is added to include the "prettier-plugin-go-template" plugin for go-template files - `overrides` is added to specify the parser as "go-template" for files with the ".html" extension * chore(base.scss): improve font rendering by adding font smoothing properties to all elements feat(base.scss): add user-select: none to body to disable text selection feat(base.scss): add overscroll-behavior-y: none to html and body to disable vertical scrolling on overscroll feat(base.scss): add cursor: pointer to anchor tags and buttons for better user experience feat(font.scss): add font-face declaration for HelveticaNow font refactor(media.scss): remove unused file feat(mixins.scss): add min-width and max-width mixins for responsive design feat(reset.scss): add the new CSS reset version 1.8.4 feat(reset.scss): remove all styles from User-Agent-Stylesheet except for the display property feat(reset.scss): set box-sizing: border-box for all elements feat(reset.scss): revert cursor style for anchor tags and buttons feat(reset.scss): remove list styles (bullets/numbers) from ol, ul, and menu feat(reset.scss): set max-inline-size and max-block-size to 100% for images feat(reset.scss): set border-collapse: collapse for tables feat(reset.scss): set -webkit-user-select: auto for input and textarea to fix Safari issue feat(reset.scss): revert white-space property for textarea on Safari feat(reset.scss): set -webkit-appearance: revert for meter element feat(reset.scss): revert all styles for preformatted text feat(reset.scss): unset color for input placeholder feat(reset.scss): remove default dot sign for lists feat(reset.scss): set display: none for elements with hidden attribute feat(reset.scss): revert styles for contenteditable elements feat(reset.scss): set -webkit-user-drag: element for draggable elements feat(reset.scss): revert native behavior for modal dialogs feat(typography.scss): set line-height, font-size, and font-family for body feat(typography.scss): increase font-size for tablet and laptop breakpoints * feat: add custom cursor styles Add a new file `_customCursor.scss` to the `assets/css/_partial` directory. This file contains styles for a custom cursor. The `.cursor` class is used to position the cursor and set its appearance. The `.active` class is used to display the cursor. The `.cursorInner` class is used to position the inner content of the cursor. --- refactor: remove unused footer styles Delete the file `_footer.scss` from the `assets/css/_partial` directory. This file contains styles for the footer section of the page. The styles are no longer used and can be safely removed. --- refactor: remove unused image styles Delete the files `_imagesDesktop.scss` and `_imagesMobile.scss` from the `assets/css/_partial` directory. These files contain styles for displaying images on desktop and mobile devices. The styles are no longer used and can be safely removed. --- feat: add navigation styles Add a new file `_nav.scss` to the `assets/css/_partial` directory. This file contains styles for the navigation bar. The styles define the layout and appearance of the navigation bar, including its position, background color, and alignment of its contents. The styles also include media queries to adjust the layout for smaller screens. --- refactor: remove unused overlay styles Delete the file `_overlay.scss` from the `assets/css/_partial` directory. This file contains styles for an overlay element. The styles are no longer used and can be safely removed. --- feat: add stage styles Add a new file `_stage.scss` to the `assets/css/_partial` directory. This file contains styles for the stage element, which is used to display images. The styles define the position and size of the stage, as well as the appearance of the images within it. --- feat: add stage navigation overlay styles Add a new file `_stageNav.scss` to the `assets/css/_partial` directory. This file contains styles for the stage navigation overlay. The styles define the position and size of the overlay, as well as its appearance and behavior. The overlay is used for navigation within the stage. * chore(variables.scss): update variable names and values for better readability and consistency chore(style.scss): reorganize import statements for better organization and readability * fix(main.ts): import correct functions from utils module feat(stage.ts): implement stage navigation functionality feat(stageNav.ts): implement stage navigation overlay functionality feat(state.ts): implement state management for index and threshold feat(utils.ts): add utility functions for increment and decrement * fix(index.html): fix doctype declaration to use lowercase 'doctype' for HTML5 compliance fix(index.html): fix meta tag indentation for better readability fix(index.html): fix indentation of head and body tags for better readability fix(index.html): fix indentation of header, main, and footer sections for better readability fix(index.html): fix indentation of script tag for better readability fix(index.html): fix indentation of closing div tag for better readability fix(index.html): fix indentation of closing body and html tags for better readability feat(index.html): add partial for navigation bar to improve website navigation fix(head.html): fix indentation of esBuildOpts variable for better readability fix(head.html): fix indentation of script tag for better readability feat(nav.html): add navigation bar partial to improve website navigation * refactor(stage.ts): change cordHist, isOpen, isAnimating, and active variables to instances of the watchable class to improve semantics and encapsulation * refactor(customCursor.ts): rename addActiveCallback to active.addWatcher for better readability and consistency refactor(stageNav.ts): rename getIsAnimating to isAnimating.get for better readability and consistency refactor(stageNav.ts): rename addActiveCallback to active.addWatcher for better readability and consistency feat(stageNav.ts): add check for isOpen.get() and isAnimating.get() before handling key events to prevent unwanted actions * chore(package.json): add prettier-plugin-go-template as a dev dependency to enable formatting of Go templates with Prettier * chore: add helvetica now font * chore(tsconfig.json): add "moduleResolution" property with value "node" to improve module resolution in the project configuration * refactor(stage.ts): rename class 'watchable' to 'Watchable' for consistency and clarity feat(utils.ts): add Watchable class to provide a generic watchable object with getter, setter, and watcher functionality --- .idea/.gitignore | 5 - .idea/bridget.iml | 12 - .idea/codeStyles/Project.xml | 93 - .idea/codeStyles/codeStyleConfig.xml | 5 - .idea/inspectionProfiles/Project_Default.xml | 6 - .idea/jsLibraryMappings.xml | 6 - .idea/jsLinters/eslint.xml | 6 - .idea/modules.xml | 8 - .idea/vcs.xml | 6 - .idea/watcherTasks.xml | 4 - .prettierrc.json | 23 +- assets/css/_core/_base.scss | 28 +- assets/css/_core/_font.scss | 6 + assets/css/_core/_media.scss | 0 assets/css/_core/_mixins.scss | 28 + assets/css/_core/_reset.scss | 103 + assets/css/_core/_typography.scss | 14 + assets/css/_partial/_customCursor.scss | 21 + assets/css/_partial/_footer.scss | 75 - assets/css/_partial/_imagesDesktop.scss | 52 - assets/css/_partial/_imagesMobile.scss | 16 - assets/css/_partial/_nav.scss | 44 + assets/css/_partial/_overlay.scss | 15 - assets/css/_partial/_stage.scss | 22 + assets/css/_partial/_stageNav.scss | 21 + assets/css/_variables.scss | 22 +- assets/css/style.scss | 22 +- assets/ts/customCursor.ts | 38 + assets/ts/dataFetch.ts | 14 - assets/ts/desktop.ts | 165 -- assets/ts/elemGen.ts | 55 - assets/ts/imageCache.ts | 18 - assets/ts/indexDisp.ts | 17 - assets/ts/main.ts | 39 +- assets/ts/mobile.ts | 24 - assets/ts/nav.ts | 59 + assets/ts/overlay.ts | 204 -- assets/ts/resources.ts | 21 + assets/ts/stage.ts | 184 ++ assets/ts/stageNav.ts | 87 + assets/ts/state.ts | 68 + assets/ts/thresholdCtl.ts | 51 - assets/ts/utils.ts | 148 +- layouts/index.html | 79 +- layouts/partials/head.html | 5 +- layouts/partials/nav.html | 27 + package.json | 4 + pnpm-lock.yaml | 2088 ++++++++++++++++++ static/fonts/HelveticaNowText-Regular.woff | Bin 0 -> 51704 bytes tsconfig.json | 5 +- 50 files changed, 2963 insertions(+), 1100 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/bridget.iml delete mode 100644 .idea/codeStyles/Project.xml delete mode 100644 .idea/codeStyles/codeStyleConfig.xml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/jsLibraryMappings.xml delete mode 100644 .idea/jsLinters/eslint.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/watcherTasks.xml create mode 100644 assets/css/_core/_font.scss delete mode 100644 assets/css/_core/_media.scss create mode 100644 assets/css/_core/_mixins.scss create mode 100644 assets/css/_core/_reset.scss create mode 100644 assets/css/_core/_typography.scss create mode 100644 assets/css/_partial/_customCursor.scss delete mode 100644 assets/css/_partial/_footer.scss delete mode 100644 assets/css/_partial/_imagesDesktop.scss delete mode 100644 assets/css/_partial/_imagesMobile.scss create mode 100644 assets/css/_partial/_nav.scss delete mode 100644 assets/css/_partial/_overlay.scss create mode 100644 assets/css/_partial/_stage.scss create mode 100644 assets/css/_partial/_stageNav.scss create mode 100644 assets/ts/customCursor.ts delete mode 100644 assets/ts/dataFetch.ts delete mode 100644 assets/ts/desktop.ts delete mode 100644 assets/ts/elemGen.ts delete mode 100644 assets/ts/imageCache.ts delete mode 100644 assets/ts/indexDisp.ts delete mode 100644 assets/ts/mobile.ts create mode 100644 assets/ts/nav.ts delete mode 100644 assets/ts/overlay.ts create mode 100644 assets/ts/resources.ts create mode 100644 assets/ts/stage.ts create mode 100644 assets/ts/stageNav.ts create mode 100644 assets/ts/state.ts delete mode 100644 assets/ts/thresholdCtl.ts create mode 100644 layouts/partials/nav.html create mode 100644 pnpm-lock.yaml create mode 100644 static/fonts/HelveticaNowText-Regular.woff diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index b58b603..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/bridget.iml b/.idea/bridget.iml deleted file mode 100644 index 0c8867d..0000000 --- a/.idea/bridget.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 70eea87..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 03d9549..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml deleted file mode 100644 index d23208f..0000000 --- a/.idea/jsLibraryMappings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml deleted file mode 100644 index b269b71..0000000 --- a/.idea/jsLinters/eslint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index a6ba3d7..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml deleted file mode 100644 index fb0d65a..0000000 --- a/.idea/watcherTasks.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json index 4107696..263da8b 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,9 +1,18 @@ { -"useTabs": false, -"tabWidth": 2, -"printWidth": 88, -"singleQuote": true, -"trailingComma": "none", -"bracketSpacing": true, -"semi": false + "useTabs": false, + "tabWidth": 2, + "printWidth": 88, + "singleQuote": true, + "trailingComma": "none", + "bracketSpacing": true, + "semi": false, + "plugins": ["prettier-plugin-go-template"], + "overrides": [ + { + "files": ["*.html"], + "options": { + "parser": "go-template" + } + } + ] } diff --git a/assets/css/_core/_base.scss b/assets/css/_core/_base.scss index d65d850..865a8c5 100644 --- a/assets/css/_core/_base.scss +++ b/assets/css/_core/_base.scss @@ -1,14 +1,20 @@ -html { - font-family: $global-font-family; - overflow: hidden; - position: relative; - scroll-behavior: smooth; +* { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } body { - background-color: white; - height: 100vh; - margin: 0; - overflow: hidden; - line-height: 1.5; -} \ No newline at end of file + user-select: none; + background: white; +} + +html, +body { + overscroll-behavior-y: none; +} + +a, +button { + cursor: pointer; +} + diff --git a/assets/css/_core/_font.scss b/assets/css/_core/_font.scss new file mode 100644 index 0000000..397038e --- /dev/null +++ b/assets/css/_core/_font.scss @@ -0,0 +1,6 @@ +@font-face { + font-family: HelveticaNow; + src: url('/fonts/HelveticaNowText-Regular.woff') format('woff'); + font-weight: 400; + font-style: normal; +} diff --git a/assets/css/_core/_media.scss b/assets/css/_core/_media.scss deleted file mode 100644 index e69de29..0000000 diff --git a/assets/css/_core/_mixins.scss b/assets/css/_core/_mixins.scss new file mode 100644 index 0000000..d818128 --- /dev/null +++ b/assets/css/_core/_mixins.scss @@ -0,0 +1,28 @@ +$breakpoints: ( + 'mobile': 375px, + 'tablet': 768px, + 'laptop': 1024px, + 'desktop': 1440px +) !default; + +// Breakpoints + +@mixin min-width($breakpoint) { + @if map-has-key($breakpoints, $breakpoint) { + @media (min-width: map-get($breakpoints, $breakpoint)) { + @content; + } + } @else { + @error "Unfortunately, no value could be retrieved from `#{$breakpoint}`. " + "Available breakpoints are: #{map-keys($breakpoints)}."; + } +} + +@mixin max-width($breakpoint) { + @if map-has-key($breakpoints, $breakpoint) { + @media (max-width: (map-get($breakpoints, $breakpoint) - 1px)) { + @content; + } + } @else { + @error "Unfortunately, no value could be retrieved from `#{$breakpoint}`. " + "Available breakpoints are: #{map-keys($breakpoints)}."; + } +} diff --git a/assets/css/_core/_reset.scss b/assets/css/_core/_reset.scss new file mode 100644 index 0000000..0de3854 --- /dev/null +++ b/assets/css/_core/_reset.scss @@ -0,0 +1,103 @@ +/*** + The new CSS reset - version 1.8.4 (last updated 14.2.2023) + GitHub page: https://github.com/elad2412/the-new-css-reset +***/ + +/* + Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property + - The "symbol *" part is to solve Firefox SVG sprite bug + */ +*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { + all: unset; + display: revert; +} + +/* Preferred box-sizing value */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Reapply the pointer cursor for anchor tags */ +a, +button { + cursor: revert; +} + +/* Remove list styles (bullets/numbers) */ +ol, +ul, +menu { + list-style: none; +} + +/* For images to not be able to exceed their container */ +img { + max-inline-size: 100%; + max-block-size: 100%; +} + +/* removes spacing between cells in tables */ +table { + border-collapse: collapse; +} + +/* Safari - solving issue when using user-select:none on the text input doesn't working */ +input, +textarea { + -webkit-user-select: auto; +} + +/* revert the 'white-space' property for textarea elements on Safari */ +textarea { + white-space: revert; +} + +/* minimum style to allow to style meter element */ +meter { + -webkit-appearance: revert; + appearance: revert; +} + +/* preformatted text - use only for this feature */ +:where(pre) { + all: revert; +} + +/* reset default text opacity of input placeholder */ +::placeholder { + color: unset; +} + +/* remove default dot (•) sign */ +::marker { + content: initial; +} + +/* fix the feature of 'hidden' attribute. + display:revert; revert to element instead of attribute */ +:where([hidden]) { + display: none; +} + +/* revert for bug in Chromium browsers + - fix for the content editable attribute will work properly. + - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element*/ +:where([contenteditable]:not([contenteditable='false'])) { + -moz-user-modify: read-write; + -webkit-user-modify: read-write; + overflow-wrap: break-word; + -webkit-line-break: after-white-space; + -webkit-user-select: auto; +} + +/* apply back the draggable feature - exist only in Chromium and Safari */ +:where([draggable='true']) { + -webkit-user-drag: element; +} + +/* Revert Modal native behavior */ +:where(dialog:modal) { + all: revert; +} diff --git a/assets/css/_core/_typography.scss b/assets/css/_core/_typography.scss new file mode 100644 index 0000000..00d5d55 --- /dev/null +++ b/assets/css/_core/_typography.scss @@ -0,0 +1,14 @@ +@import 'mixins'; + +body { + line-height: 1.2; + font-size: 16px; + font-family: HelveticaNow, helvetica, arial, sans-serif; + + @include min-width('tablet') { + font-size: 18px; + } + @include min-width('laptop') { + font-size: 19px; + } +} diff --git a/assets/css/_partial/_customCursor.scss b/assets/css/_partial/_customCursor.scss new file mode 100644 index 0000000..591c8f5 --- /dev/null +++ b/assets/css/_partial/_customCursor.scss @@ -0,0 +1,21 @@ +.cursor { + position: fixed; + z-index: var(--z-cursor); + top: 0; + left: 0; + + display: none; + cursor: none; + pointer-events: none; + + color: white; + mix-blend-mode: difference; +} + +.active { + display: block; +} + +.cursorInner { + transform: translate3d(-50%, -50%, 0); +} diff --git a/assets/css/_partial/_footer.scss b/assets/css/_partial/_footer.scss deleted file mode 100644 index 62823fb..0000000 --- a/assets/css/_partial/_footer.scss +++ /dev/null @@ -1,75 +0,0 @@ -footer { - max-height: fit-content; - position: fixed; - bottom: 0; - left: 0; - right: 0; - z-index: 22; - background-color: #fff; - height: 38px; - display: flex; - justify-content: space-between; - align-items: center; - font-size: 20px; - line-height: 1.5; - padding: 4px 9px; - float: none; - - .footer_name { - } - - .footer_categoryWrapper { - .footer_category { - cursor: pointer; - } - - .selected { - text-decoration: underline; - font-style: italic; - } - } - - .footer_threshold { - button { - border: none; - background-color: transparent; - margin: 0; - font-size: 20px; - padding: 0 4px; - cursor: pointer; - } - - .thid{ - display: inline-block; - text-align: center; - width: 48px; - } - } - - .footer_imageIndex { - margin: 0; - - .ftid { - display: inline-block; - text-align: center; - width: 7px; - } - } -} - -@media only screen and (max-width: 768px) { - footer { - top: 0; - padding: 3px 8px; - font-size: 17px; - height: 31px; - - .footer_threshold { - display: none; - } - - .footer_imageIndex { - display: none; - } - } -} \ No newline at end of file diff --git a/assets/css/_partial/_imagesDesktop.scss b/assets/css/_partial/_imagesDesktop.scss deleted file mode 100644 index a3e3a86..0000000 --- a/assets/css/_partial/_imagesDesktop.scss +++ /dev/null @@ -1,52 +0,0 @@ -.imagesDesktop { - - img { - position: absolute; - top: 0; - left: 0; - object-fit: contain; - max-height: 50vmin; - max-width: 100vw; - - &[data-status='null'] { - opacity: 1; - } - - &[data-status='top'] { - opacity: 1; - max-height: calc(100vh - var(--footer-height));; - transition-property: transform, max-height; - transition-timing-function: ease-in-out; - transition-duration: 0.5s, 0.5s; - } - - &[data-status='trail'] { - opacity: 0; - margin-top: 40px; - transition-property: opacity, margin-top; - transition-timing-function: ease-out; - transition-duration: 0.2s; - } - - &[data-status='resumeTop'] { - opacity: 1; - max-height: 50vmin; - transition-property: max-height, transform; - transition-timing-function: ease-in-out; - transition-duration: 0.7s, 0.5s; - } - - &[data-status='resume'] { - opacity: 1; - margin-top: 0; - transition-property: opacity, margin-top; - transition-timing-function: ease-out; - transition-duration: 0.2s; - } - - &[data-status='overlay'] { - opacity: 1; - max-height: calc(100vh - var(--footer-height)); - } - } -} \ No newline at end of file diff --git a/assets/css/_partial/_imagesMobile.scss b/assets/css/_partial/_imagesMobile.scss deleted file mode 100644 index ea94e08..0000000 --- a/assets/css/_partial/_imagesMobile.scss +++ /dev/null @@ -1,16 +0,0 @@ -.imagesMobile { - height: 100vh; - overflow: scroll; - position: relative; - - img { - height: 20vh; - width: 60vw; - object-fit: contain; - position: sticky; - top: 50vh; - margin-left: 0; - margin-right: 0; - margin-bottom: 20vh; - } -} \ No newline at end of file diff --git a/assets/css/_partial/_nav.scss b/assets/css/_partial/_nav.scss new file mode 100644 index 0000000..6b4d1c3 --- /dev/null +++ b/assets/css/_partial/_nav.scss @@ -0,0 +1,44 @@ +@import '../_core/mixins'; +$tablet: map-get($breakpoints, 'tablet') - 1; + +nav { + display: flex; + justify-content: space-between; + align-items: center; + + width: 100%; + height: var(--nav-height); + padding: 0 var(--space-standard); + + position: fixed; + bottom: 0; + background: white; + + z-index: var(--z-nav); + + // Maintain functionality while container is locked + pointer-events: all; +} + +.num { + width: 0.625em; + display: inline-block; + text-align: center; +} + +.current { + font-style: italic; + text-decoration: underline; +} + +@media (max-width: $tablet), (hover: none) { + nav { + top: 0; + position: sticky; + } + + .index, + .threshold { + display: none; + } +} diff --git a/assets/css/_partial/_overlay.scss b/assets/css/_partial/_overlay.scss deleted file mode 100644 index 9c55b08..0000000 --- a/assets/css/_partial/_overlay.scss +++ /dev/null @@ -1,15 +0,0 @@ -.overlay_cursor { - position: fixed; - top: 0; - left: 0; - mix-blend-mode: difference; - font-size: 19px; - box-sizing: border-box; - cursor: none; - user-select: none; - - .cursor_innerText { - color: white; - transform: translate3d(-50%, -50%, 0); - } -} \ No newline at end of file diff --git a/assets/css/_partial/_stage.scss b/assets/css/_partial/_stage.scss new file mode 100644 index 0000000..ef53850 --- /dev/null +++ b/assets/css/_partial/_stage.scss @@ -0,0 +1,22 @@ +.stage { + position: relative; + overflow: hidden; + width: 100vw; + height: calc(var(--window-height) - var(--nav-height)); + + cursor: pointer; + + img { + position: absolute; + top: 0; + left: 0; + + width: 100vw; + height: var(--window-height); + object-fit: contain; + + transform: scale(0.6); + opacity: 0; + pointer-events: none; + } +} diff --git a/assets/css/_partial/_stageNav.scss b/assets/css/_partial/_stageNav.scss new file mode 100644 index 0000000..c347049 --- /dev/null +++ b/assets/css/_partial/_stageNav.scss @@ -0,0 +1,21 @@ +.navOverlay { + position: fixed; + top: 0; + left: 0; + z-index: var(--z-nav-gallery); + + width: 100vw; + height: calc(var(--window-height) - var(--nav-height)); + + display: flex; + cursor: none; + + &:not(.active) { + pointer-events: none; + display: none; + } + + .overlay { + flex: 1; + } +} diff --git a/assets/css/_variables.scss b/assets/css/_variables.scss index 193d082..b126326 100644 --- a/assets/css/_variables.scss +++ b/assets/css/_variables.scss @@ -1,14 +1,12 @@ -// ============================== -// Variables -// ============================== - -// ========== Global ========== // -// Font and Line Height -$global-font-family: system-ui, -apple-system, BlinkMacSystemFont, PingFang SC, Microsoft YaHei UI, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, Helvetica, Arial, sans-serif !default; -$global-font-size: 16px; -$global-font-weight: 400; -$global-line-height: 1.5rem; +@import '_core/mixins'; :root { - --footer-height: 38px; -} \ No newline at end of file + --window-height: 100vh; + --nav-height: 2rem; + --space-standard: 0.625rem; + + --z-curtain: 200; + --z-nav-gallery: 500; + --z-cursor: 600; + --z-nav: 800; +} diff --git a/assets/css/style.scss b/assets/css/style.scss index 7df3db5..96c8842 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -1,15 +1,13 @@ @charset "utf-8"; -@import "_variables"; +@import '_core/reset'; +@import '_core/font'; +@import '_core/typography'; +@import '_core/mixins'; +@import '_variables'; +@import '_core/base'; -@import "_core/base"; - -@import "_core/media"; - -@import "_partial/imagesDesktop"; - -@import "_partial/imagesMobile"; - -@import "_partial/footer"; - -@import "_partial/overlay"; \ No newline at end of file +@import '_partial/customCursor'; +@import '_partial/nav'; +@import '_partial/stage'; +@import '_partial/stageNav'; diff --git a/assets/ts/customCursor.ts b/assets/ts/customCursor.ts new file mode 100644 index 0000000..030e1a2 --- /dev/null +++ b/assets/ts/customCursor.ts @@ -0,0 +1,38 @@ +import { active } from './stage' + +let cursor: HTMLDivElement + +// create cursor +cursor = document.createElement('div') +cursor.className = 'cursor' +cursor.classList.add('active') +// create cursor inner +const cursorInner = document.createElement('div') +cursorInner.className = 'cursorInner' +// append cursor inner to cursor +cursor.append(cursorInner) + +function onMouse(e: MouseEvent) { + const x = e.clientX + const y = e.clientY + cursor.style.transform = `translate3d(${x}px, ${y}px, 0)` +} + +export function initCustomCursor(): void { + // append cursor to main + document.getElementById('main')!.append(cursor) + // bind mousemove event to window + window.addEventListener('mousemove', onMouse) + // add active callback + active.addWatcher(() => { + if (active.get()) { + cursor.classList.add('active') + } else { + cursor.classList.remove('active') + } + }) +} + +export function setCustomCursor(text: string): void { + cursorInner.innerText = text +} diff --git a/assets/ts/dataFetch.ts b/assets/ts/dataFetch.ts deleted file mode 100644 index 07db65d..0000000 --- a/assets/ts/dataFetch.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { type ImageData } from './utils' - -// fetch images info from JSON -const imageArrayElement = document.getElementById('images_array') as HTMLScriptElement -const rawImageArray = imageArrayElement.textContent as string -export const imagesArray: ImageData[] = JSON.parse(rawImageArray).sort( - (a: ImageData, b: ImageData) => { - if (a.index < b.index) { - return -1 - } - return 1 - } -) -export const imagesArrayLen: number = imagesArray.length diff --git a/assets/ts/desktop.ts b/assets/ts/desktop.ts deleted file mode 100644 index dba830e..0000000 --- a/assets/ts/desktop.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { overlayEnable } from './overlay' -import { - calcImageIndex, - center, - delay, - mouseToTransform, - pushIndex, - type position, - hideImage -} from './utils' -import { thresholdIndex, thresholdSensitivityArray } from './thresholdCtl' -import { imgIndexSpanUpdate } from './indexDisp' -import { imagesArrayLen } from './dataFetch' -import { imagesDivNodes as images } from './elemGen' - -// global index for "activated" -export let globalIndex: number = 0 -// last position set as "activated" -let last: position = { x: 0, y: 0 } -export let trailingImageIndexes: number[] = [] -// only used in overlay disable, for storing positions temporarily -export let transformCache: string[] = [] -// abort controller for enter overlay event listener -let EnterOverlayClickAbCtl = new AbortController() -// stack depth of images array -export let stackDepth: number = 5 -export let lastStackDepth: number = 5 - -export const addEnterOverlayEL = (e: HTMLImageElement): void => { - EnterOverlayClickAbCtl.abort() - EnterOverlayClickAbCtl = new AbortController() - e.addEventListener( - 'click', - () => { - void enterOverlay() - }, - { - passive: true, - once: true, - signal: EnterOverlayClickAbCtl.signal - } - ) -} - -// activate top image -const activate = (index: number, mouseX: number, mouseY: number): void => { - addEnterOverlayEL(images[index]) - if (stackDepth !== lastStackDepth) { - trailingImageIndexes.push(index) - refreshStack() - lastStackDepth = stackDepth - } - const indexesNum: number = pushIndex( - index, - trailingImageIndexes, - stackDepth, - images, - imagesArrayLen - ) - // set img position - images[index].style.transform = mouseToTransform(mouseX, mouseY, true, true) - images[index].dataset.status = 'null' - // reset z index - for (let i = indexesNum; i > 0; i--) { - images[trailingImageIndexes[i - 1]].style.zIndex = `${i}` - } - images[index].style.visibility = 'visible' - last = { x: mouseX, y: mouseY } -} - -// Compare the current mouse position with the last activated position -const distanceFromLast = (x: number, y: number): number => { - return Math.hypot(x - last.x, y - last.y) -} - -// handle mouse move -export const handleOnMove = (e: MouseEvent): void => { - // meet threshold - if ( - distanceFromLast(e.clientX, e.clientY) > - window.innerWidth / thresholdSensitivityArray[thresholdIndex] - ) { - // calculate the actual index - const imageIndex = calcImageIndex(globalIndex, imagesArrayLen) - // show top image and change index - activate(imageIndex, e.clientX, e.clientY) - imgIndexSpanUpdate(imageIndex + 1, imagesArrayLen) - // self increment - globalIndexInc() - } -} - -async function enterOverlay(): Promise { - // stop images animation - window.removeEventListener('mousemove', handleOnMove) - // get index array length - const indexesNum: number = trailingImageIndexes.length - for (let i = 0; i < indexesNum; i++) { - // create image element - const e: HTMLImageElement = images[trailingImageIndexes[i]] - // cache images' position - transformCache.push(e.style.transform) - // set style for the images - if (i === indexesNum - 1) { - e.style.transitionDelay = `${0.1 * i + 0.2}s, ${0.1 * i + 0.2 + 0.5}s` - e.dataset.status = 'top' - center(e) - } else { - e.style.transitionDelay = `${0.1 * i}s` - e.dataset.status = 'trail' - } - } - // sleep - await delay(stackDepth * 100 + 100 + 1000) - // post process - for (let i = 0; i < indexesNum; i++) { - images[trailingImageIndexes[i]].style.transitionDelay = '' - if (i === indexesNum - 1) { - images[trailingImageIndexes[i]].dataset.status = 'overlay' - } else { - images[trailingImageIndexes[i]].style.visibility = 'hidden' - } - } - // Offset previous self increment of global index (by handleOnMove) - globalIndexDec() - // overlay init - overlayEnable() -} - -// initialization -export const trackMouseInit = (): void => { - window.addEventListener('mousemove', handleOnMove) -} - -export const globalIndexDec = (): void => { - globalIndex-- -} - -export const globalIndexInc = (): void => { - globalIndex++ -} - -export const emptyTransformCache = (): void => { - transformCache = [] -} - -export const emptyTrailingImageIndexes = (): void => { - trailingImageIndexes = [] -} - -export const setStackDepth = (newStackDepth: number): void => { - if (stackDepth !== newStackDepth) { - lastStackDepth = stackDepth - stackDepth = newStackDepth - } -} - -export const refreshStack = (): void => { - const l: number = trailingImageIndexes.length - if (stackDepth < lastStackDepth && l > stackDepth) { - const times: number = l - stackDepth - for (let i = 0; i < times; i++) - hideImage(images[trailingImageIndexes.shift() as number]) - } -} diff --git a/assets/ts/elemGen.ts b/assets/ts/elemGen.ts deleted file mode 100644 index 65963f9..0000000 --- a/assets/ts/elemGen.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { imagesArray, imagesArrayLen } from './dataFetch' -import { createImgElement } from './utils' - -// get components of overlay -export let overlayCursor: HTMLDivElement -export let cursorInnerContent: HTMLDivElement -export let imagesDivNodes: NodeListOf - -const mainDiv = document.getElementById('main') as HTMLDivElement - -const passDesktopElements = (): void => { - overlayCursor = document - .getElementsByClassName('overlay_cursor') - .item(0) as HTMLDivElement - cursorInnerContent = document - .getElementsByClassName('cursor_innerText') - .item(0) as HTMLDivElement - imagesDivNodes = document.getElementsByClassName('imagesDesktop')[0] - .childNodes as NodeListOf -} - -const passMobileElements = (): void => { - imagesDivNodes = document.getElementsByClassName('imagesMobile')[0] - .childNodes as NodeListOf -} - -const createCursorDiv = (): HTMLDivElement => { - const cursorDiv: HTMLDivElement = document.createElement('div') - cursorDiv.className = 'overlay_cursor' - const innerTextDiv: HTMLDivElement = document.createElement('div') - innerTextDiv.className = 'cursor_innerText' - cursorDiv.appendChild(innerTextDiv) - return cursorDiv -} - -export const createDesktopElements = (): void => { - mainDiv.appendChild(createCursorDiv()) - const imagesDiv: HTMLDivElement = document.createElement('div') - imagesDiv.className = 'imagesDesktop' - for (let i = 0; i < imagesArrayLen; i++) { - imagesDiv.appendChild(createImgElement(imagesArray[i])) - } - mainDiv.appendChild(imagesDiv) - passDesktopElements() -} - -export const createMobileElements = (): void => { - const imagesDiv: HTMLDivElement = document.createElement('div') - imagesDiv.className = 'imagesMobile' - for (let i = 0; i < imagesArrayLen; i++) { - imagesDiv.appendChild(createImgElement(imagesArray[i])) - } - mainDiv.appendChild(imagesDiv) - passMobileElements() -} diff --git a/assets/ts/imageCache.ts b/assets/ts/imageCache.ts deleted file mode 100644 index feaa88d..0000000 --- a/assets/ts/imageCache.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { imagesArray, imagesArrayLen } from './dataFetch' -import { preloadImage, calcImageIndex } from './utils' - -let lastIndex: number = 0 - -export const preloader = (index: number): void => { - if (lastIndex === index) { - for (let i: number = -2; i <= 1; i++) - preloadImage(imagesArray[calcImageIndex(index + i, imagesArrayLen)].url) - } else if (lastIndex > index) { - for (let i: number = 1; i <= 3; i++) - preloadImage(imagesArray[calcImageIndex(index - i, imagesArrayLen)].url) - } else { - for (let i: number = 1; i <= 3; i++) - preloadImage(imagesArray[calcImageIndex(index + i, imagesArrayLen)].url) - } - lastIndex = index -} diff --git a/assets/ts/indexDisp.ts b/assets/ts/indexDisp.ts deleted file mode 100644 index e772230..0000000 --- a/assets/ts/indexDisp.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { duper } from './utils' - -// update index of displaying image -export const imgIndexSpanUpdate = (numOne: number, numTwo: number): void => { - // footer index number display module - const footerIndexDisp = document.getElementsByClassName('ftid') - const numOneString: string = duper(numOne) - const numTwoString: string = duper(numTwo) - for (let i: number = 0; i <= 7; i++) { - const footerIndex = footerIndexDisp[i] as HTMLSpanElement - if (i > 3) { - footerIndex.innerText = numTwoString[i - 4] - } else { - footerIndex.innerText = numOneString[i] - } - } -} diff --git a/assets/ts/main.ts b/assets/ts/main.ts index e1e3b1b..2d58579 100644 --- a/assets/ts/main.ts +++ b/assets/ts/main.ts @@ -1,28 +1,13 @@ -import { createDesktopElements, createMobileElements } from './elemGen' -import { imgIndexSpanUpdate } from './indexDisp' -import { trackMouseInit } from './desktop' -import { thresholdCtlInit } from './thresholdCtl' -import { imagesArrayLen } from './dataFetch' -import { vwRefreshInit } from './overlay' -import { preloader } from './imageCache' -import { getDeviceType } from './utils' -import { renderImages } from './mobile' +import { initResources } from './resources' +import { initState } from './state' +import { initCustomCursor } from './customCursor' +import { initNav } from './nav' +import { initStage } from './stage' +import { initStageNav } from './stageNav' -const desktopInit = (): void => { - createDesktopElements() - preloader(0) - vwRefreshInit() - imgIndexSpanUpdate(0, imagesArrayLen) - thresholdCtlInit() - trackMouseInit() -} - -const mobileInit = (): void => { - createMobileElements() - vwRefreshInit() - imgIndexSpanUpdate(0, imagesArrayLen) - renderImages() - console.log('mobile') -} - -getDeviceType().desktop ? mobileInit() : desktopInit() +initCustomCursor() +const ijs = initResources() +initState(ijs.length) +initStage(ijs) +initStageNav() +initNav() diff --git a/assets/ts/mobile.ts b/assets/ts/mobile.ts deleted file mode 100644 index 8f66752..0000000 --- a/assets/ts/mobile.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { imagesDivNodes as images } from './elemGen' -import { imagesArrayLen } from './dataFetch' - -export const renderImages = (): void => { - images.forEach((img: HTMLImageElement, idx: number): void => { - const randomX: number = Math.floor(Math.random() * 35) + 2 - let randomY: number - - // random Y calculation - if (idx === 0) { - randomY = 68 - } else if (idx === 1) { - randomY = 44 - } else if (idx === imagesArrayLen - 1) { - randomY = 100 - } else { - randomY = Math.floor(Math.random() * 51) + 2 - } - - img.style.transform = `translate(${randomX}vw, -${randomY}%)` - img.style.marginTop = `${idx === 1 ? 70 : 0}vh` - img.style.visibility = 'visible' - }) -} diff --git a/assets/ts/nav.ts b/assets/ts/nav.ts new file mode 100644 index 0000000..6a8b235 --- /dev/null +++ b/assets/ts/nav.ts @@ -0,0 +1,59 @@ +import { getState, incThreshold, decThreshold } from './state' +import { expand } from './utils' + +// threshold div +const thresholdDiv = document + .getElementsByClassName('threshold') + .item(0) as HTMLDivElement + +// threshold nums span +const thresholdDispNums = Array.from( + thresholdDiv.getElementsByClassName('num') +) as HTMLSpanElement[] + +// threshold buttons +const decButton = thresholdDiv + .getElementsByClassName('dec') + .item(0) as HTMLButtonElement +const incButton = thresholdDiv + .getElementsByClassName('inc') + .item(0) as HTMLButtonElement + +// index div +const indexDiv = document.getElementsByClassName('index').item(0) as HTMLDivElement + +// index nums span +const indexDispNums = Array.from( + indexDiv.getElementsByClassName('num') +) as HTMLSpanElement[] + +export function initNav() { + // init threshold text + updateThresholdText() + // init index text + updateIndexText() + // event listeners + decButton.addEventListener('click', () => decThreshold()) + incButton.addEventListener('click', () => incThreshold()) +} + +// helper + +export function updateThresholdText(): void { + const thresholdValue: string = expand(getState().threshold) + thresholdDispNums.forEach((e: HTMLSpanElement, i: number) => { + e.innerText = thresholdValue[i] + }) +} + +export function updateIndexText(): void { + const indexValue: string = expand(getState().index + 1) + const indexLength: string = expand(getState().length) + indexDispNums.forEach((e: HTMLSpanElement, i: number) => { + if (i < 4) { + e.innerText = indexValue[i] + } else { + e.innerText = indexLength[i - 4] + } + }) +} diff --git a/assets/ts/overlay.ts b/assets/ts/overlay.ts deleted file mode 100644 index 08e883f..0000000 --- a/assets/ts/overlay.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { delay, center, calcImageIndex, mouseToTransform, pushIndex } from './utils' -import { - handleOnMove, - globalIndex, - globalIndexDec, - globalIndexInc, - trailingImageIndexes, - transformCache, - emptyTransformCache, - emptyTrailingImageIndexes, - stackDepth, - addEnterOverlayEL -} from './desktop' -import { imagesArrayLen } from './dataFetch' -import { imgIndexSpanUpdate } from './indexDisp' -import { overlayCursor, cursorInnerContent, imagesDivNodes as images } from './elemGen' - -let oneThird: number = Math.round(window.innerWidth / 3) - -// set cursor text -const setCursorText = (text: string): void => { - cursorInnerContent.innerText = text -} - -// overlay cursor event handler -const setTextPos = (e: MouseEvent): void => { - overlayCursor.style.transform = mouseToTransform(e.clientX, e.clientY, false, true) -} - -// disable listeners -const disableListener = (): void => { - window.removeEventListener('mousemove', handleOverlayMouseMove) - overlayCursor.removeEventListener('click', handleOverlayClick) -} - -// enable overlay -export const overlayEnable = (): void => { - // show the overlay components - overlayCursor.style.zIndex = '21' - // set overlay event listeners - setListener() -} - -// disable overlay -export const overlayDisable = (): void => { - // hide the overlay components - overlayCursor.style.zIndex = '-1' - // set overlay cursor text content to none - setCursorText('') - // disable overlay event listeners - disableListener() -} - -// handle close click -async function handleCloseClick(): Promise { - // disable overlay - overlayDisable() - // get length of indexes and empty indexes array - const indexesNum = trailingImageIndexes.length - emptyTrailingImageIndexes() - // prepare animation - for (let i: number = 0; i < indexesNum; i++) { - // get element from index and store the index - const index: number = calcImageIndex(globalIndex - i, imagesArrayLen) - const e: HTMLImageElement = images[index] - trailingImageIndexes.unshift(index) - // set z index for the image element - e.style.zIndex = `${indexesNum - i - 1}` - // set different style for trailing and top image - if (i === 0) { - // set position - e.style.transform = transformCache[indexesNum - i - 1] - // set transition delay - e.style.transitionDelay = '0s, 0.7s' - // set status for css - e.dataset.status = 'resumeTop' - } else { - // set position - e.style.transform = transformCache[indexesNum - i - 1] - // set transition delay - e.style.transitionDelay = `${1.2 + 0.1 * i - 0.1}s` - // set status for css - e.dataset.status = 'resume' - } - // style process complete, show the image - e.style.visibility = 'visible' - } - // halt the function while animation is running - await delay(1200 + stackDepth * 100 + 100) - // add back enter overlay event listener to top image - addEnterOverlayEL(images[calcImageIndex(globalIndex, imagesArrayLen)]) - // clear unused status and transition delay - for (let i: number = 0; i < indexesNum; i++) { - const index: number = calcImageIndex(globalIndex - i, imagesArrayLen) - images[index].dataset.status = 'null' - images[index].style.transitionDelay = '' - } - // Add back previous self increment of global index (by handleOnMove) - globalIndexInc() - // add back mousemove event listener - window.addEventListener('mousemove', handleOnMove, { passive: true }) - // empty the position array cache - emptyTransformCache() -} - -const handleSideClick = (CLD: boolean): void => { - // get last displayed image's index - const imgIndex: number = calcImageIndex(globalIndex, imagesArrayLen) - // change global index and get current displayed image's index - CLD ? globalIndexInc() : globalIndexDec() - const currImgIndex: number = calcImageIndex(globalIndex, imagesArrayLen) - // store current displayed image's index - CLD - ? pushIndex( - currImgIndex, - trailingImageIndexes, - stackDepth, - images, - imagesArrayLen, - false, - false - ) - : pushIndex( - currImgIndex, - trailingImageIndexes, - stackDepth, - images, - imagesArrayLen, - true, - false - ) - // hide last displayed image - images[imgIndex].style.visibility = 'hidden' - images[imgIndex].dataset.status = 'trail' - // process the image going to display - center(images[currImgIndex]) - images[currImgIndex].dataset.status = 'overlay' - // process complete, show the image - images[currImgIndex].style.visibility = 'visible' - // change index display - imgIndexSpanUpdate(currImgIndex + 1, imagesArrayLen) -} - -// change text and position of overlay cursor -const handleOverlayMouseMove = (e: MouseEvent): void => { - // set text position - setTextPos(e) - // set text content - if (e.clientX < oneThird) { - setCursorText('PREV') - overlayCursor.dataset.status = 'PREV' - } else if (e.clientX < oneThird * 2) { - setCursorText('CLOSE') - overlayCursor.dataset.status = 'CLOSE' - } else { - setCursorText('NEXT') - overlayCursor.dataset.status = 'NEXT' - } -} - -const handleOverlayClick = (): void => { - switch (overlayCursor.dataset.status) { - case 'PREV': - handleSideClick(false) - break - case 'CLOSE': - void handleCloseClick() - break - case 'NEXT': - handleSideClick(true) - break - } -} - -// set event listener -const setListener = (): void => { - // add mouse move event listener (for overlay text cursor) - window.addEventListener('mousemove', handleOverlayMouseMove, { passive: true }) - // add close/prev/next click event listener - overlayCursor.addEventListener('click', handleOverlayClick, { passive: true }) -} - -export const vwRefreshInit = (): void => { - window.addEventListener( - 'resize', - () => { - // refresh value of one third - oneThird = Math.round(window.innerWidth / 3) - // reset footer height - const r = document.querySelector(':root') as HTMLStyleElement - if (window.innerWidth > 768) { - r.style.setProperty('--footer-height', '38px') - } else { - r.style.setProperty('--footer-height', '31px') - } - // recenter image (only in overlay) - if ( - images[calcImageIndex(globalIndex, imagesArrayLen)].dataset.status === 'overlay' - ) - center(images[calcImageIndex(globalIndex, imagesArrayLen)]) - }, - { passive: true } - ) -} diff --git a/assets/ts/resources.ts b/assets/ts/resources.ts new file mode 100644 index 0000000..4eb0b06 --- /dev/null +++ b/assets/ts/resources.ts @@ -0,0 +1,21 @@ +// data structure for images info +export interface ImageJSON { + index: number + url: string + imgH: number + imgW: number + pColor: string + sColor: string +} + +export function initResources(): ImageJSON[] { + const imagesJson = document.getElementById('imagesSource') as HTMLScriptElement + return JSON.parse(imagesJson.textContent as string).sort( + (a: ImageJSON, b: ImageJSON) => { + if (a.index < b.index) { + return -1 + } + return 1 + } + ) +} diff --git a/assets/ts/stage.ts b/assets/ts/stage.ts new file mode 100644 index 0000000..8b22caf --- /dev/null +++ b/assets/ts/stage.ts @@ -0,0 +1,184 @@ +import { incIndex, getState } from './state' +import { gsap, Power3 } from 'gsap' +import { ImageJSON } from './resources' +import { Watchable } from './utils' + +// types + +export type HistoryItem = { i: number; x: number; y: number } + +// variables + +let imgs: HTMLImageElement[] = [] +let last = { x: 0, y: 0 } +export const cordHist = new Watchable([]) +export const isOpen = new Watchable(false) +export const isAnimating = new Watchable(false) +export const active = new Watchable(false) + +// getter + +function getElTrail(): HTMLImageElement[] { + return cordHist.get().map((item) => imgs[item.i]) +} + +function getElTrailCurrent(): HTMLImageElement[] { + return getElTrail().slice(-getState().trailLength) +} + +function getElTrailInactive(): HTMLImageElement[] { + const elTrailCurrent = getElTrailCurrent() + return elTrailCurrent.slice(0, elTrailCurrent.length - 1) +} + +function getElCurrent(): HTMLImageElement { + const elTrail = getElTrail() + return elTrail[elTrail.length - 1] +} + +// main functions + +// on mouse +function onMouse(e: MouseEvent): void { + if (isOpen.get() || isAnimating.get()) return + const cord = { x: e.clientX, y: e.clientY } + const travelDist = Math.hypot(cord.x - last.x, cord.y - last.y) + + if (travelDist > getState().threshold) { + last = cord + incIndex() + + const newHist = { i: getState().index, ...cord } + cordHist.set([...cordHist.get(), newHist].slice(-getState().length)) + } +} + +// set image position with gsap +function setPositions(): void { + const elTrail = getElTrail() + if (!elTrail.length) return + + gsap.set(elTrail, { + x: (i: number) => cordHist.get()[i].x - window.innerWidth / 2, + y: (i: number) => cordHist.get()[i].y - window.innerHeight / 2, + opacity: (i: number) => + i + 1 + getState().trailLength <= cordHist.get().length ? 0 : 1, + zIndex: (i: number) => i, + scale: 0.6 + }) + + if (isOpen.get()) { + gsap.set(imgs, { opacity: 0 }) + gsap.set(getElCurrent(), { opacity: 1, x: 0, y: 0, scale: 1 }) + } +} + +// open image into navigation +function expandImage(): void { + if (isAnimating.get()) return + + isOpen.set(true) + isAnimating.set(true) + + const tl = gsap.timeline() + // move down and hide trail inactive + tl.to(getElTrailInactive(), { + y: '+=20', + ease: Power3.easeIn, + stagger: 0.075, + duration: 0.3, + delay: 0.1, + opacity: 0 + }) + // current move to center + tl.to(getElCurrent(), { + x: 0, + y: 0, + ease: Power3.easeInOut, + duration: 0.7, + delay: 0.3 + }) + // current expand + tl.to(getElCurrent(), { + delay: 0.1, + scale: 1, + ease: Power3.easeInOut + }) + // finished + tl.then(() => { + isAnimating.set(false) + }) +} + +// close navigation and back to stage +export function minimizeImage(): void { + if (isAnimating.get()) return + + isOpen.set(false) + isAnimating.set(true) + + const tl = gsap.timeline() + // shrink current + tl.to(getElCurrent(), { + scale: 0.6, + duration: 0.6, + ease: Power3.easeInOut + }) + // move current to original position + tl.to(getElCurrent(), { + delay: 0.3, + duration: 0.7, + ease: Power3.easeInOut, + x: cordHist.get()[cordHist.get().length - 1].x - window.innerWidth / 2, + y: cordHist.get()[cordHist.get().length - 1].y - window.innerHeight / 2 + }) + // show trail inactive + tl.to(getElTrailInactive(), { + y: '-=20', + ease: Power3.easeOut, + stagger: -0.1, + duration: 0.3, + opacity: 1 + }) + // finished + tl.then(() => { + isAnimating.set(false) + }) +} + +// init + +export function initStage(ijs: ImageJSON[]): void { + // create stage element + createStage(ijs) + // get stage + const stage = document.getElementsByClassName('stage').item(0) as HTMLDivElement + // get image elements + imgs = Array.from(stage.getElementsByTagName('img')) + // event listeners + stage.addEventListener('click', () => expandImage()) + stage.addEventListener('keydown', () => expandImage()) + window.addEventListener('mousemove', onMouse) + // watchers + isOpen.addWatcher(() => active.set(isOpen.get() && !isAnimating.get())) + isAnimating.addWatcher(() => active.set(isOpen.get() && !isAnimating.get())) + cordHist.addWatcher(() => setPositions()) +} + +// hepler + +function createStage(ijs: ImageJSON[]): void { + // create container for images + const stage: HTMLDivElement = document.createElement('div') + stage.className = 'stage' + // append images to container + for (let ij of ijs) { + const e = document.createElement('img') + e.src = ij.url + e.height = ij.imgH + e.width = ij.imgW + e.alt = 'image' + stage.append(e) + } + document.getElementById('main')!.append(stage) +} diff --git a/assets/ts/stageNav.ts b/assets/ts/stageNav.ts new file mode 100644 index 0000000..f37009c --- /dev/null +++ b/assets/ts/stageNav.ts @@ -0,0 +1,87 @@ +import { setCustomCursor } from './customCursor' +import { decIndex, incIndex, getState } from './state' +import { increment, decrement } from './utils' +import { cordHist, isOpen, isAnimating, active, minimizeImage } from './stage' + +type NavItem = (typeof navItems)[number] +const navItems = ['prev', 'close', 'next'] as const + +// main functions + +function handleClick(type: NavItem) { + switch (type) { + case 'prev': + prevImage() + break + case 'close': + minimizeImage() + break + case 'next': + nextImage() + break + } +} + +function handleKey(e: KeyboardEvent) { + if (isOpen.get() || isAnimating.get()) return + switch (e.key) { + case 'ArrowLeft': + prevImage() + break + case 'Escape': + minimizeImage() + break + case 'ArrowRight': + nextImage() + break + } +} + +// init + +export function initStageNav() { + const navOverlay = document.createElement('div') + navOverlay.className = 'navOverlay' + for (let navItem of navItems) { + const overlay = document.createElement('div') + overlay.className = 'overlay' + overlay.addEventListener('click', () => handleClick(navItem)) + overlay.addEventListener('keydown', () => handleClick(navItem)) + overlay.addEventListener('mouseover', () => setCustomCursor(navItem)) + overlay.addEventListener('focus', () => setCustomCursor(navItem)) + navOverlay.append(overlay) + } + active.addWatcher(() => { + if (active.get()) { + navOverlay.classList.add('active') + } else { + navOverlay.classList.remove('active') + } + }) + document.getElementById('main')!.append(navOverlay) + window.addEventListener('keydown', handleKey) +} + +// hepler + +function nextImage() { + if (isAnimating.get()) return + cordHist.set( + cordHist.get().map((item) => { + return { ...item, i: increment(item.i, getState().length) } + }) + ) + + incIndex() +} + +function prevImage() { + if (isAnimating.get()) return + cordHist.set( + cordHist.get().map((item) => { + return { ...item, i: decrement(item.i, getState().length) } + }) + ) + + decIndex() +} diff --git a/assets/ts/state.ts b/assets/ts/state.ts new file mode 100644 index 0000000..4aebfe9 --- /dev/null +++ b/assets/ts/state.ts @@ -0,0 +1,68 @@ +import { increment, decrement } from './utils' +import { updateIndexText, updateThresholdText } from './nav' + +const thresholds = [ + { threshold: 20, trailLength: 20 }, + { threshold: 40, trailLength: 10 }, + { threshold: 80, trailLength: 5 }, + { threshold: 140, trailLength: 5 }, + { threshold: 200, trailLength: 5 } +] + +const defaultState = { + index: -1, + length: 0, + threshold: thresholds[2].threshold, + trailLength: thresholds[2].trailLength +} + +export type State = typeof defaultState + +let state = defaultState + +export function getState(): State { + // return a copy of state + return Object.create( + Object.getPrototypeOf(state), + Object.getOwnPropertyDescriptors(state) + ) +} + +export function initState(length: number): void { + state.length = length +} + +export function setIndex(index: number): void { + state.index = index + updateIndexText() +} + +export function incIndex(): void { + state.index = increment(state.index, state.length) + updateIndexText() +} + +export function decIndex(): void { + state.index = decrement(state.index, state.length) + updateIndexText() +} + +export function incThreshold(): void { + state = updateThreshold(state, 1) + updateThresholdText() +} + +export function decThreshold(): void { + state = updateThreshold(state, -1) + updateThresholdText() +} + +// helper + +function updateThreshold(state: State, inc: number): State { + const i = thresholds.findIndex((t) => state.threshold === t.threshold) + const newItems = thresholds[i + inc] + // out of range + if (!newItems) return state + return { ...state, ...newItems } +} diff --git a/assets/ts/thresholdCtl.ts b/assets/ts/thresholdCtl.ts deleted file mode 100644 index 30f2a21..0000000 --- a/assets/ts/thresholdCtl.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { duper } from './utils' -import { setStackDepth } from './desktop' - -// get threshold display element -const thresholdDisp = document.getElementsByClassName('thid').item(0) as HTMLSpanElement - -// threshold data -const threshold: number[] = [0, 40, 80, 120, 160, 200] -export const thresholdSensitivityArray: number[] = [100, 40, 18, 14, 9, 5] -export let thresholdIndex: number = 2 - -export const stackDepthArray: number[] = [15, 8, 5, 5, 5, 5] - -// update inner text of threshold display element -const thresholdUpdate = (): void => { - thresholdDisp.innerText = duper(threshold[thresholdIndex]) -} - -const stackDepthUpdate = (): void => { - setStackDepth(stackDepthArray[thresholdIndex]) -} - -// threshold control initialization -export const thresholdCtlInit = (): void => { - thresholdUpdate() - const dec = document.getElementById('thresholdDec') as HTMLButtonElement - dec.addEventListener( - 'click', - function () { - if (thresholdIndex > 0) { - thresholdIndex-- - thresholdUpdate() - stackDepthUpdate() - } - }, - { passive: true } - ) - - const inc = document.getElementById('thresholdInc') as HTMLButtonElement - inc.addEventListener( - 'click', - function () { - if (thresholdIndex < 5) { - thresholdIndex++ - thresholdUpdate() - stackDepthUpdate() - } - }, - { passive: true } - ) -} diff --git a/assets/ts/utils.ts b/assets/ts/utils.ts index 04da9fa..e2e21e7 100644 --- a/assets/ts/utils.ts +++ b/assets/ts/utils.ts @@ -1,145 +1,33 @@ -export interface ImageData { - index: string - url: string - imgH: string - imgW: string - pColor: string - sColor: string +export function increment(num: number, length: number): number { + return (num + 1) % length } -export interface position { - x: number - y: number +export function decrement(num: number, length: number): number { + return (num + length - 1) % length } -export interface deviceType { - mobile: boolean - tablet: boolean - desktop: boolean -} - -// 0 to 0001, 25 to 0025 -export const duper = (num: number): string => { +export function expand(num: number): string { return ('0000' + num.toString()).slice(-4) } -export const mouseToTransform = ( - x: number, - y: number, - centerCorrection: boolean = true, - accelerate: boolean = false -): string => { - return `translate${accelerate ? '3d' : ''}(${ - centerCorrection ? `calc(${x}px - 50%)` : `${x}px` - }, ${centerCorrection ? `calc(${y}px - 50%)` : `${y}px`}${accelerate ? ', 0' : ''})` +export function isMobile(): boolean { + return window.matchMedia('(hover: none)').matches } -// eslint-disable-next-line @typescript-eslint/promise-function-async -export function delay(ms: number): Promise { - return new Promise((resolve) => setTimeout(resolve, ms)) -} +export class Watchable { + constructor(private obj: T) {} + private watchers: (() => void)[] = [] -// remove all event listeners from a node -export const removeAllEventListeners = (e: Node): Node => { - return e.cloneNode(true) -} - -// center top div -export const center = (e: HTMLElement): void => { - const x: number = window.innerWidth / 2 - let y: number - if (window.innerWidth > 768) { - y = (window.innerHeight - 38) / 2 - } else { - y = (window.innerHeight - 31) / 2 + 31 + get(): T { + return this.obj } - e.style.transform = mouseToTransform(x, y) -} -export const createImgElement = (input: ImageData): HTMLImageElement => { - const img = document.createElement('img') - img.setAttribute('src', input.url) - img.setAttribute('alt', '') - img.setAttribute('height', input.imgH) - img.setAttribute('width', input.imgW) - img.style.visibility = 'hidden' - img.dataset.status = 'trail' - // img.style.backgroundImage = `linear-gradient(15deg, ${input.pColor}, ${input.sColor})` - return img -} + set(e: T): void { + this.obj = e + this.watchers.forEach((watcher) => watcher()) + } -export const calcImageIndex = (index: number, imgCounts: number): number => { - if (index >= 0) { - return index % imgCounts - } else { - return (imgCounts + (index % imgCounts)) % imgCounts + addWatcher(watcher: () => void): void { + this.watchers.push(watcher) } } - -export const preloadImage = (src: string): void => { - const cache = new Image() - cache.src = src -} - -export const getDeviceType = (): deviceType => { - const ua: string = navigator.userAgent - const result: deviceType = { mobile: false, tablet: false, desktop: false } - if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) { - result.mobile = true - result.tablet = true - } else if ( - /Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test( - ua - ) - ) { - result.mobile = true - } else result.desktop = true - return result -} - -export const hideImage = (e: HTMLImageElement): void => { - e.style.visibility = 'hidden' - e.dataset.status = 'trail' -} - -export const pushIndex = ( - index: number, - indexesArray: number[], - stackDepth: number, - imagesArray: NodeListOf, - imagesArrayLen: number, - invertFlag: boolean = false, - autoHideFlag: boolean = true -): number => { - let indexesNum: number = indexesArray.length - // create variable overflow to store the tail index - let overflow: number - if (!invertFlag) { - // if stack is full, push the tail index out and hide the image - if (indexesNum === stackDepth) { - // insert - indexesArray.push(index) - // pop out - overflow = indexesArray.shift() as number - // auto hide tail image - if (autoHideFlag) hideImage(imagesArray[overflow]) - } else { - indexesArray.push(index) - indexesNum += 1 - } - } else { - // if stack is full, push the tail index out and hide the image - if (indexesNum === stackDepth) { - // insert - indexesArray.unshift(calcImageIndex(index - stackDepth + 1, imagesArrayLen)) - // pop out - overflow = indexesArray.pop() as number - // auto hide tail image - if (autoHideFlag) hideImage(imagesArray[overflow]) - } else { - indexesArray.unshift(calcImageIndex(index - indexesNum + 1, imagesArrayLen)) - indexesNum += 1 - } - } - return indexesNum -} diff --git a/layouts/index.html b/layouts/index.html index edb54b2..9fe8cfc 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -1,43 +1,42 @@ - + - - - - {{ partial "head.html" . }} - {{ .Title }} - - -
- {{ partial "header.html" . }} -
-
- {{ $sourcePath := "images" }} - {{ $gallery := site.GetPage $sourcePath }} - {{ with $gallery.Resources.ByType "image" }} - {{ $index := len . }} - {{ $.Scratch.Add "img" slice }} - {{ range . }} - {{ $index = sub $index 1}} - {{ $colors := .Colors }} - {{ $pColor := index $colors 0 }} - {{ $sColor := "#ccc" }} - {{ if gt (len $colors) 1 }} - {{ $sColor = index $colors 1 }} + + + + {{ partial "head.html" . }} + {{ .Title }} + + +
+ {{ partial "header.html" . }} +
+
+ {{ $sourcePath := "images" }} + {{ $gallery := site.GetPage $sourcePath }} + {{ with $gallery.Resources.ByType "image" }} + {{ $index := len . }} + {{ $.Scratch.Add "img" slice }} + {{ range . }} + {{ $index = sub $index 1 }} + {{ $colors := .Colors }} + {{ $pColor := index $colors 0 }} + {{ $sColor := "#ccc" }} + {{ if gt (len $colors) 1 }} + {{ $sColor = index $colors 1 }} + {{ end }} + {{ $resize := .Resize "x2000 webp Lanczos q70" }} + {{ $.Scratch.Add "img" (dict + "index" (int $index) + "url" (string .RelPermalink) + "imgH" (int .Height) + "imgW" (int .Width) + "pColor" (string $pColor) + "sColor" (string $sColor)) + }} + {{ end }} + {{ end }} - {{ $resize := .Resize "x2000 webp Lanczos q70" }} - {{ $.Scratch.Add "img" (dict - "index" (string $index) - "url" (string .RelPermalink) - "imgH" (string .Height) - "imgW" (string .Width) - "pColor" (string $pColor) - "sColor" (string $sColor)) }} - {{ end }} - - {{ end }} -
-
- {{ partial "footer.html" . }} -
- +
+ {{ partial "nav.html" . }} + diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 9c3d6da..c3d84e6 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -3,6 +3,7 @@ {{- $options := dict "targetPath" "css/style.min.css" "enableSourceMap" true -}} {{- $style = dict "Context" . "ToCSS" $options | merge $style -}} {{- partial "plugin/style.html" $style -}} +{{- $esBuildOpts := dict "minify" hugo.IsProduction -}} -{{ $script := resources.Get "ts/main.ts" | js.Build }} - \ No newline at end of file +{{- $script := resources.Get "ts/main.ts" | js.Build $esBuildOpts -}} + diff --git a/layouts/partials/nav.html b/layouts/partials/nav.html new file mode 100644 index 0000000..f1b9a4a --- /dev/null +++ b/layouts/partials/nav.html @@ -0,0 +1,27 @@ + diff --git a/package.json b/package.json index b3c2d2b..baa9db1 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,10 @@ "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-promise": "^6.1.1", "prettier": "3.0.3", + "prettier-plugin-go-template": "^0.0.15", "typescript": "^5.1.6" + }, + "dependencies": { + "gsap": "^3.12.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..7e4ecca --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2088 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + gsap: + specifier: ^3.12.2 + version: 3.12.2 + +devDependencies: + '@typescript-eslint/eslint-plugin': + specifier: ^6.3.0 + version: 6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0)(typescript@5.1.6) + '@typescript-eslint/parser': + specifier: ^6.3.0 + version: 6.3.0(eslint@8.47.0)(typescript@5.1.6) + eslint: + specifier: ^8.47.0 + version: 8.47.0 + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.0.0(eslint@8.47.0) + eslint-config-standard: + specifier: ^17.1.0 + version: 17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0) + eslint-config-standard-with-typescript: + specifier: ^37.0.0 + version: 37.0.0(@typescript-eslint/eslint-plugin@6.3.0)(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0)(typescript@5.1.6) + eslint-plugin-import: + specifier: ^2.28.0 + version: 2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0) + eslint-plugin-n: + specifier: ^16.0.1 + version: 16.0.1(eslint@8.47.0) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.0.0(eslint-config-prettier@9.0.0)(eslint@8.47.0)(prettier@3.0.1) + eslint-plugin-promise: + specifier: ^6.1.1 + version: 6.1.1(eslint@8.47.0) + prettier: + specifier: 3.0.1 + version: 3.0.1 + prettier-plugin-go-template: + specifier: ^0.0.15 + version: 0.0.15(prettier@3.0.1) + typescript: + specifier: ^5.1.6 + version: 5.1.6 + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.47.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.47.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.6.2: + resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.2: + resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.21.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.47.0: + resolution: {integrity: sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.10: + resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@pkgr/utils@2.4.2: + resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dependencies: + cross-spawn: 7.0.3 + fast-glob: 3.3.1 + is-glob: 4.0.3 + open: 9.1.0 + picocolors: 1.0.0 + tslib: 2.6.1 + dev: true + + /@types/json-schema@7.0.12: + resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/semver@7.5.0: + resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} + dev: true + + /@typescript-eslint/eslint-plugin@6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0)(typescript@5.1.6): + resolution: {integrity: sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.6.2 + '@typescript-eslint/parser': 6.3.0(eslint@8.47.0)(typescript@5.1.6) + '@typescript-eslint/scope-manager': 6.3.0 + '@typescript-eslint/type-utils': 6.3.0(eslint@8.47.0)(typescript@5.1.6) + '@typescript-eslint/utils': 6.3.0(eslint@8.47.0)(typescript@5.1.6) + '@typescript-eslint/visitor-keys': 6.3.0 + debug: 4.3.4 + eslint: 8.47.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare: 1.4.0 + natural-compare-lite: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.1(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@5.62.0(eslint@8.47.0)(typescript@5.1.6): + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) + debug: 4.3.4 + eslint: 8.47.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.3.0(eslint@8.47.0)(typescript@5.1.6): + resolution: {integrity: sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.3.0 + '@typescript-eslint/types': 6.3.0 + '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6) + '@typescript-eslint/visitor-keys': 6.3.0 + debug: 4.3.4 + eslint: 8.47.0 + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.62.0: + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + dev: true + + /@typescript-eslint/scope-manager@6.3.0: + resolution: {integrity: sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.3.0 + '@typescript-eslint/visitor-keys': 6.3.0 + dev: true + + /@typescript-eslint/type-utils@6.3.0(eslint@8.47.0)(typescript@5.1.6): + resolution: {integrity: sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6) + '@typescript-eslint/utils': 6.3.0(eslint@8.47.0)(typescript@5.1.6) + debug: 4.3.4 + eslint: 8.47.0 + ts-api-utils: 1.0.1(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/types@6.3.0: + resolution: {integrity: sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.1.6): + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + tsutils: 3.21.0(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@6.3.0(typescript@5.1.6): + resolution: {integrity: sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.3.0 + '@typescript-eslint/visitor-keys': 6.3.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.1(typescript@5.1.6) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.3.0(eslint@8.47.0)(typescript@5.1.6): + resolution: {integrity: sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) + '@types/json-schema': 7.0.12 + '@types/semver': 7.5.0 + '@typescript-eslint/scope-manager': 6.3.0 + '@typescript-eslint/types': 6.3.0 + '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6) + eslint: 8.47.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.62.0: + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@6.3.0: + resolution: {integrity: sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.3.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /acorn-jsx@5.3.2(acorn@8.10.0): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.10.0 + dev: true + + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + + /array-includes@3.1.6: + resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + get-intrinsic: 1.2.1 + is-string: 1.0.7 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.findlastindex@1.2.2: + resolution: {integrity: sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + es-shim-unscopables: 1.0.0 + get-intrinsic: 1.2.1 + dev: true + + /array.prototype.flat@1.3.1: + resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + es-shim-unscopables: 1.0.0 + dev: true + + /array.prototype.flatmap@1.3.1: + resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + es-shim-unscopables: 1.0.0 + dev: true + + /arraybuffer.prototype.slice@1.0.1: + resolution: {integrity: sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.2 + define-properties: 1.2.0 + get-intrinsic: 1.2.1 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /big-integer@1.6.51: + resolution: {integrity: sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==} + engines: {node: '>=0.6'} + dev: true + + /bplist-parser@0.2.0: + resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} + engines: {node: '>= 5.10.0'} + dependencies: + big-integer: 1.6.51 + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /builtins@5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.5.4 + dev: true + + /bundle-name@3.0.0: + resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} + engines: {node: '>=12'} + dependencies: + run-applescript: 5.0.0 + dev: true + + /call-bind@1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /default-browser-id@3.0.0: + resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} + engines: {node: '>=12'} + dependencies: + bplist-parser: 0.2.0 + untildify: 4.0.0 + dev: true + + /default-browser@4.0.0: + resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} + engines: {node: '>=14.16'} + dependencies: + bundle-name: 3.0.0 + default-browser-id: 3.0.0 + execa: 7.2.0 + titleize: 3.0.0 + dev: true + + /define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + dev: true + + /define-properties@1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /es-abstract@1.22.1: + resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.1 + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.2.1 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.12.3 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.0 + safe-array-concat: 1.0.0 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.7 + string.prototype.trimend: 1.0.6 + string.prototype.trimstart: 1.0.6 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.11 + dev: true + + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + has-tostringtag: 1.0.0 + dev: true + + /es-shim-unscopables@1.0.0: + resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + dependencies: + has: 1.0.3 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier@9.0.0(eslint@8.47.0): + resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.47.0 + dev: true + + /eslint-config-standard-with-typescript@37.0.0(@typescript-eslint/eslint-plugin@6.3.0)(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0)(typescript@5.1.6): + resolution: {integrity: sha512-V8I/Q1eFf9tiOuFHkbksUdWO3p1crFmewecfBtRxXdnvb71BCJx+1xAknlIRZMwZioMX3/bPtMVCZsf1+AjjOw==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.52.0 + eslint: ^8.0.1 + eslint-plugin-import: ^2.25.2 + eslint-plugin-n: '^15.0.0 || ^16.0.0 ' + eslint-plugin-promise: ^6.0.0 + typescript: '*' + dependencies: + '@typescript-eslint/eslint-plugin': 6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0)(typescript@5.1.6) + '@typescript-eslint/parser': 5.62.0(eslint@8.47.0)(typescript@5.1.6) + eslint: 8.47.0 + eslint-config-standard: 17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0) + eslint-plugin-import: 2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0) + eslint-plugin-n: 16.0.1(eslint@8.47.0) + eslint-plugin-promise: 6.1.1(eslint@8.47.0) + typescript: 5.1.6 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-config-standard@17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0): + resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: ^8.0.1 + eslint-plugin-import: ^2.25.2 + eslint-plugin-n: '^15.0.0 || ^16.0.0 ' + eslint-plugin-promise: ^6.0.0 + dependencies: + eslint: 8.47.0 + eslint-plugin-import: 2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0) + eslint-plugin-n: 16.0.1(eslint@8.47.0) + eslint-plugin-promise: 6.1.1(eslint@8.47.0) + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.0 + resolve: 1.22.4 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.3.0)(eslint-import-resolver-node@0.3.9)(eslint@8.47.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 6.3.0(eslint@8.47.0)(typescript@5.1.6) + debug: 3.2.7 + eslint: 8.47.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es-x@7.2.0(eslint@8.47.0): + resolution: {integrity: sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) + '@eslint-community/regexpp': 4.6.2 + eslint: 8.47.0 + dev: true + + /eslint-plugin-import@2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0): + resolution: {integrity: sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 6.3.0(eslint@8.47.0)(typescript@5.1.6) + array-includes: 3.1.6 + array.prototype.findlastindex: 1.2.2 + array.prototype.flat: 1.3.1 + array.prototype.flatmap: 1.3.1 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.47.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.3.0)(eslint-import-resolver-node@0.3.9)(eslint@8.47.0) + has: 1.0.3 + is-core-module: 2.13.0 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.6 + object.groupby: 1.0.0 + object.values: 1.1.6 + resolve: 1.22.4 + semver: 6.3.1 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-n@16.0.1(eslint@8.47.0): + resolution: {integrity: sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) + builtins: 5.0.1 + eslint: 8.47.0 + eslint-plugin-es-x: 7.2.0(eslint@8.47.0) + ignore: 5.2.4 + is-core-module: 2.13.0 + minimatch: 3.1.2 + resolve: 1.22.4 + semver: 7.5.4 + dev: true + + /eslint-plugin-prettier@5.0.0(eslint-config-prettier@9.0.0)(eslint@8.47.0)(prettier@3.0.1): + resolution: {integrity: sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.47.0 + eslint-config-prettier: 9.0.0(eslint@8.47.0) + prettier: 3.0.1 + prettier-linter-helpers: 1.0.0 + synckit: 0.8.5 + dev: true + + /eslint-plugin-promise@6.1.1(eslint@8.47.0): + resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + eslint: 8.47.0 + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.47.0: + resolution: {integrity: sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) + '@eslint-community/regexpp': 4.6.2 + '@eslint/eslintrc': 2.1.2 + '@eslint/js': 8.47.0 + '@humanwhocodes/config-array': 0.11.10 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.21.0 + graphemer: 1.4.0 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /execa@7.2.0: + resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} + engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 4.3.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.7 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /function.prototype.name@1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /get-intrinsic@1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-proto: 1.0.1 + has-symbols: 1.0.3 + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@13.21.0: + resolution: {integrity: sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /gsap@3.12.2: + resolution: {integrity: sha512-EkYnpG8qHgYBFAwsgsGEqvT1WUidX0tt/ijepx7z8EUJHElykg91RvW1XbkT59T0gZzzszOpjQv7SE41XuIXyQ==} + dev: false + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /human-signals@4.3.1: + resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} + engines: {node: '>=14.18.0'} + dev: true + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /internal-slot@1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.0: + resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} + dependencies: + has: 1.0.3 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: true + + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.11 + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npm-run-path@5.1.0: + resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.fromentries@2.0.6: + resolution: {integrity: sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /object.groupby@1.0.0: + resolution: {integrity: sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + get-intrinsic: 1.2.1 + dev: true + + /object.values@1.1.6: + resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /open@9.1.0: + resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} + engines: {node: '>=14.16'} + dependencies: + default-browser: 4.0.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 2.2.0 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier-plugin-go-template@0.0.15(prettier@3.0.1): + resolution: {integrity: sha512-WqU92E1NokWYNZ9mLE6ijoRg6LtIGdLMePt2C7UBDjXeDH9okcRI3zRqtnWR4s5AloiqyvZ66jNBAa9tmRY5EQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + prettier: ^3.0.0 + dependencies: + prettier: 3.0.1 + ulid: 2.3.0 + dev: true + + /prettier@3.0.1: + resolution: {integrity: sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /regexp.prototype.flags@1.5.0: + resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + functions-have-names: 1.2.3 + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve@1.22.4: + resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + hasBin: true + dependencies: + is-core-module: 2.13.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /run-applescript@5.0.0: + resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} + engines: {node: '>=12'} + dependencies: + execa: 5.1.1 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-array-concat@1.0.0: + resolution: {integrity: sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-regex: 1.1.4 + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + object-inspect: 1.12.3 + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /string.prototype.trim@1.2.7: + resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.22.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /synckit@0.8.5: + resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/utils': 2.4.2 + tslib: 2.6.1 + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /titleize@3.0.0: + resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} + engines: {node: '>=12'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /ts-api-utils@1.0.1(typescript@5.1.6): + resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.1.6 + dev: true + + /tsconfig-paths@3.14.2: + resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tslib@2.6.1: + resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==} + dev: true + + /tsutils@3.21.0(typescript@5.1.6): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 5.1.6 + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typescript@5.1.6: + resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /ulid@2.3.0: + resolution: {integrity: sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==} + hasBin: true + dev: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-typed-array@1.1.11: + resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/static/fonts/HelveticaNowText-Regular.woff b/static/fonts/HelveticaNowText-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..5bdb0c59dc42c60e126e121c31b1527f4dd6118b GIT binary patch literal 51704 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 Date: Sun, 29 Oct 2023 12:52:44 +0800 Subject: [PATCH 02/13] Gsap (#122) * feat: add gsap to deps * chore: migrate to pnpm * refractor: change var name * chore(.idea): remove unnecessary files and configurations Remove the following files and configurations from the .idea directory: - .gitignore: Remove default ignored files. - bridget.iml: Remove module file. - codeStyles/Project.xml: Remove project code style configuration. - codeStyles/codeStyleConfig.xml: Remove project code style configuration. - inspectionProfiles/Project_Default.xml: Remove project inspection profile. - jsLibraryMappings.xml: Remove JavaScript library mappings. - jsLinters/eslint.xml: Remove ESLint configuration. - modules.xml: Remove project module configuration. - vcs.xml: Remove VCS directory mapping. - watcherTasks.xml: Remove project tasks options. * chore(.prettierrc.json): update Prettier configuration to include support for go-template files and improve code formatting settings The Prettier configuration file (.prettierrc.json) has been updated with the following changes: - `useTabs` is set to `false` to use spaces for indentation - `tabWidth` is set to `2` to specify the number of spaces for each indentation level - `printWidth` is set to `88` to limit the line length to 88 characters - `singleQuote` is set to `true` to use single quotes for strings - `trailingComma` is set to `none` to remove trailing commas in arrays and objects - `bracketSpacing` is set to `true` to add spaces inside brackets - `semi` is set to `false` to remove semicolons at the end of statements - `plugins` is added to include the "prettier-plugin-go-template" plugin for go-template files - `overrides` is added to specify the parser as "go-template" for files with the ".html" extension * chore(base.scss): improve font rendering by adding font smoothing properties to all elements feat(base.scss): add user-select: none to body to disable text selection feat(base.scss): add overscroll-behavior-y: none to html and body to disable vertical scrolling on overscroll feat(base.scss): add cursor: pointer to anchor tags and buttons for better user experience feat(font.scss): add font-face declaration for HelveticaNow font refactor(media.scss): remove unused file feat(mixins.scss): add min-width and max-width mixins for responsive design feat(reset.scss): add the new CSS reset version 1.8.4 feat(reset.scss): remove all styles from User-Agent-Stylesheet except for the display property feat(reset.scss): set box-sizing: border-box for all elements feat(reset.scss): revert cursor style for anchor tags and buttons feat(reset.scss): remove list styles (bullets/numbers) from ol, ul, and menu feat(reset.scss): set max-inline-size and max-block-size to 100% for images feat(reset.scss): set border-collapse: collapse for tables feat(reset.scss): set -webkit-user-select: auto for input and textarea to fix Safari issue feat(reset.scss): revert white-space property for textarea on Safari feat(reset.scss): set -webkit-appearance: revert for meter element feat(reset.scss): revert all styles for preformatted text feat(reset.scss): unset color for input placeholder feat(reset.scss): remove default dot sign for lists feat(reset.scss): set display: none for elements with hidden attribute feat(reset.scss): revert styles for contenteditable elements feat(reset.scss): set -webkit-user-drag: element for draggable elements feat(reset.scss): revert native behavior for modal dialogs feat(typography.scss): set line-height, font-size, and font-family for body feat(typography.scss): increase font-size for tablet and laptop breakpoints * feat: add custom cursor styles Add a new file `_customCursor.scss` to the `assets/css/_partial` directory. This file contains styles for a custom cursor. The `.cursor` class is used to position the cursor and set its appearance. The `.active` class is used to display the cursor. The `.cursorInner` class is used to position the inner content of the cursor. --- refactor: remove unused footer styles Delete the file `_footer.scss` from the `assets/css/_partial` directory. This file contains styles for the footer section of the page. The styles are no longer used and can be safely removed. --- refactor: remove unused image styles Delete the files `_imagesDesktop.scss` and `_imagesMobile.scss` from the `assets/css/_partial` directory. These files contain styles for displaying images on desktop and mobile devices. The styles are no longer used and can be safely removed. --- feat: add navigation styles Add a new file `_nav.scss` to the `assets/css/_partial` directory. This file contains styles for the navigation bar. The styles define the layout and appearance of the navigation bar, including its position, background color, and alignment of its contents. The styles also include media queries to adjust the layout for smaller screens. --- refactor: remove unused overlay styles Delete the file `_overlay.scss` from the `assets/css/_partial` directory. This file contains styles for an overlay element. The styles are no longer used and can be safely removed. --- feat: add stage styles Add a new file `_stage.scss` to the `assets/css/_partial` directory. This file contains styles for the stage element, which is used to display images. The styles define the position and size of the stage, as well as the appearance of the images within it. --- feat: add stage navigation overlay styles Add a new file `_stageNav.scss` to the `assets/css/_partial` directory. This file contains styles for the stage navigation overlay. The styles define the position and size of the overlay, as well as its appearance and behavior. The overlay is used for navigation within the stage. * chore(variables.scss): update variable names and values for better readability and consistency chore(style.scss): reorganize import statements for better organization and readability * fix(main.ts): import correct functions from utils module feat(stage.ts): implement stage navigation functionality feat(stageNav.ts): implement stage navigation overlay functionality feat(state.ts): implement state management for index and threshold feat(utils.ts): add utility functions for increment and decrement * fix(index.html): fix doctype declaration to use lowercase 'doctype' for HTML5 compliance fix(index.html): fix meta tag indentation for better readability fix(index.html): fix indentation of head and body tags for better readability fix(index.html): fix indentation of header, main, and footer sections for better readability fix(index.html): fix indentation of script tag for better readability fix(index.html): fix indentation of closing div tag for better readability fix(index.html): fix indentation of closing body and html tags for better readability feat(index.html): add partial for navigation bar to improve website navigation fix(head.html): fix indentation of esBuildOpts variable for better readability fix(head.html): fix indentation of script tag for better readability feat(nav.html): add navigation bar partial to improve website navigation * refactor(stage.ts): change cordHist, isOpen, isAnimating, and active variables to instances of the watchable class to improve semantics and encapsulation * refactor(customCursor.ts): rename addActiveCallback to active.addWatcher for better readability and consistency refactor(stageNav.ts): rename getIsAnimating to isAnimating.get for better readability and consistency refactor(stageNav.ts): rename addActiveCallback to active.addWatcher for better readability and consistency feat(stageNav.ts): add check for isOpen.get() and isAnimating.get() before handling key events to prevent unwanted actions * chore(package.json): add prettier-plugin-go-template as a dev dependency to enable formatting of Go templates with Prettier * chore: add helvetica now font * chore(tsconfig.json): add "moduleResolution" property with value "node" to improve module resolution in the project configuration * refactor(stage.ts): rename class 'watchable' to 'Watchable' for consistency and clarity feat(utils.ts): add Watchable class to provide a generic watchable object with getter, setter, and watcher functionality * Bump typescript from 5.1.6 to 5.2.2 (#121) Bumps [typescript](https://github.com/Microsoft/TypeScript) from 5.1.6 to 5.2.2. - [Release notes](https://github.com/Microsoft/TypeScript/releases) - [Commits](https://github.com/Microsoft/TypeScript/commits) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6b7b9a3..65b6808 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-promise": "^6.1.1", "prettier": "3.0.3", - "typescript": "^5.1.6" + "typescript": "^5.2.2" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -3301,9 +3301,9 @@ } }, "node_modules/typescript": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", - "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index baa9db1..99b5cf5 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "eslint-plugin-promise": "^6.1.1", "prettier": "3.0.3", "prettier-plugin-go-template": "^0.0.15", - "typescript": "^5.1.6" + "typescript": "^5.2.2" }, "dependencies": { "gsap": "^3.12.2" From a60ff94c7ce678574db4141e86e2f4782682436f Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 14:52:43 +0800 Subject: [PATCH 03/13] feat(customCursor.ts): add custom cursor functionality to improve user experience feat(stage.ts): implement stage functionality to display images and handle mouse events feat(stageNav.ts): add stage navigation functionality to navigate between images and close the stage fix(main.ts): fix import paths for customCursor, stage, and stageNav modules --- assets/ts/{ => desktop}/customCursor.ts | 0 assets/ts/{ => desktop}/stage.ts | 6 +++--- assets/ts/{ => desktop}/stageNav.ts | 4 ++-- assets/ts/main.ts | 6 +++--- assets/ts/mobile/collection.ts | 0 5 files changed, 8 insertions(+), 8 deletions(-) rename assets/ts/{ => desktop}/customCursor.ts (100%) rename assets/ts/{ => desktop}/stage.ts (97%) rename assets/ts/{ => desktop}/stageNav.ts (94%) create mode 100644 assets/ts/mobile/collection.ts diff --git a/assets/ts/customCursor.ts b/assets/ts/desktop/customCursor.ts similarity index 100% rename from assets/ts/customCursor.ts rename to assets/ts/desktop/customCursor.ts diff --git a/assets/ts/stage.ts b/assets/ts/desktop/stage.ts similarity index 97% rename from assets/ts/stage.ts rename to assets/ts/desktop/stage.ts index 8b22caf..94405e4 100644 --- a/assets/ts/stage.ts +++ b/assets/ts/desktop/stage.ts @@ -1,7 +1,7 @@ -import { incIndex, getState } from './state' +import { incIndex, getState } from '../state' import { gsap, Power3 } from 'gsap' -import { ImageJSON } from './resources' -import { Watchable } from './utils' +import { ImageJSON } from '../resources' +import { Watchable } from '../utils' // types diff --git a/assets/ts/stageNav.ts b/assets/ts/desktop/stageNav.ts similarity index 94% rename from assets/ts/stageNav.ts rename to assets/ts/desktop/stageNav.ts index f37009c..6d98c2c 100644 --- a/assets/ts/stageNav.ts +++ b/assets/ts/desktop/stageNav.ts @@ -1,6 +1,6 @@ import { setCustomCursor } from './customCursor' -import { decIndex, incIndex, getState } from './state' -import { increment, decrement } from './utils' +import { decIndex, incIndex, getState } from '../state' +import { increment, decrement } from '../utils' import { cordHist, isOpen, isAnimating, active, minimizeImage } from './stage' type NavItem = (typeof navItems)[number] diff --git a/assets/ts/main.ts b/assets/ts/main.ts index 2d58579..9d209bf 100644 --- a/assets/ts/main.ts +++ b/assets/ts/main.ts @@ -1,9 +1,9 @@ import { initResources } from './resources' import { initState } from './state' -import { initCustomCursor } from './customCursor' +import { initCustomCursor } from './desktop/customCursor' import { initNav } from './nav' -import { initStage } from './stage' -import { initStageNav } from './stageNav' +import { initStage } from './desktop/stage' +import { initStageNav } from './desktop/stageNav' initCustomCursor() const ijs = initResources() diff --git a/assets/ts/mobile/collection.ts b/assets/ts/mobile/collection.ts new file mode 100644 index 0000000..e69de29 From 8af74ecbaf7b55b59b1513c77a8eeb96e9703ca2 Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 14:53:31 +0800 Subject: [PATCH 04/13] deps: update dependencies --- pnpm-lock.yaml | 427 ++++++++++++++++++++++--------------------------- 1 file changed, 189 insertions(+), 238 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e4ecca..e7ad210 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,44 +11,44 @@ dependencies: devDependencies: '@typescript-eslint/eslint-plugin': - specifier: ^6.3.0 - version: 6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0)(typescript@5.1.6) + specifier: ^6.9.0 + version: 6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2) '@typescript-eslint/parser': - specifier: ^6.3.0 - version: 6.3.0(eslint@8.47.0)(typescript@5.1.6) + specifier: ^6.9.0 + version: 6.9.0(eslint@8.52.0)(typescript@5.2.2) eslint: - specifier: ^8.47.0 - version: 8.47.0 + specifier: ^8.52.0 + version: 8.52.0 eslint-config-prettier: specifier: ^9.0.0 - version: 9.0.0(eslint@8.47.0) + version: 9.0.0(eslint@8.52.0) eslint-config-standard: specifier: ^17.1.0 - version: 17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0) + version: 17.1.0(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0) eslint-config-standard-with-typescript: - specifier: ^37.0.0 - version: 37.0.0(@typescript-eslint/eslint-plugin@6.3.0)(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0)(typescript@5.1.6) + specifier: ^39.1.1 + version: 39.1.1(@typescript-eslint/eslint-plugin@6.9.0)(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0)(typescript@5.2.2) eslint-plugin-import: - specifier: ^2.28.0 - version: 2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0) + specifier: ^2.29.0 + version: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) eslint-plugin-n: - specifier: ^16.0.1 - version: 16.0.1(eslint@8.47.0) + specifier: ^16.2.0 + version: 16.2.0(eslint@8.52.0) eslint-plugin-prettier: - specifier: ^5.0.0 - version: 5.0.0(eslint-config-prettier@9.0.0)(eslint@8.47.0)(prettier@3.0.1) + specifier: ^5.0.1 + version: 5.0.1(eslint-config-prettier@9.0.0)(eslint@8.52.0)(prettier@3.0.3) eslint-plugin-promise: specifier: ^6.1.1 - version: 6.1.1(eslint@8.47.0) + version: 6.1.1(eslint@8.52.0) prettier: - specifier: 3.0.1 - version: 3.0.1 + specifier: 3.0.3 + version: 3.0.3 prettier-plugin-go-template: specifier: ^0.0.15 - version: 0.0.15(prettier@3.0.1) + version: 0.0.15(prettier@3.0.3) typescript: - specifier: ^5.1.6 - version: 5.1.6 + specifier: ^5.2.2 + version: 5.2.2 packages: @@ -57,13 +57,13 @@ packages: engines: {node: '>=0.10.0'} dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.47.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.52.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.47.0 + eslint: 8.52.0 eslint-visitor-keys: 3.4.3 dev: true @@ -89,16 +89,16 @@ packages: - supports-color dev: true - /@eslint/js@8.47.0: - resolution: {integrity: sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==} + /@eslint/js@8.52.0: + resolution: {integrity: sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@humanwhocodes/config-array@0.11.10: - resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} dependencies: - '@humanwhocodes/object-schema': 1.2.1 + '@humanwhocodes/object-schema': 2.0.1 debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: @@ -110,8 +110,8 @@ packages: engines: {node: '>=12.22'} dev: true - /@humanwhocodes/object-schema@1.2.1: - resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + /@humanwhocodes/object-schema@2.0.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} dev: true /@nodelib/fs.scandir@2.1.5: @@ -159,8 +159,8 @@ packages: resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} dev: true - /@typescript-eslint/eslint-plugin@6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0)(typescript@5.1.6): - resolution: {integrity: sha512-IZYjYZ0ifGSLZbwMqIip/nOamFiWJ9AH+T/GYNZBWkVcyNQOFGtSMoWV7RvY4poYCMZ/4lHzNl796WOSNxmk8A==} + /@typescript-eslint/eslint-plugin@6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha @@ -171,46 +171,25 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.6.2 - '@typescript-eslint/parser': 6.3.0(eslint@8.47.0)(typescript@5.1.6) - '@typescript-eslint/scope-manager': 6.3.0 - '@typescript-eslint/type-utils': 6.3.0(eslint@8.47.0)(typescript@5.1.6) - '@typescript-eslint/utils': 6.3.0(eslint@8.47.0)(typescript@5.1.6) - '@typescript-eslint/visitor-keys': 6.3.0 + '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/scope-manager': 6.9.0 + '@typescript-eslint/type-utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.9.0 debug: 4.3.4 - eslint: 8.47.0 + eslint: 8.52.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 - natural-compare-lite: 1.4.0 semver: 7.5.4 - ts-api-utils: 1.0.1(typescript@5.1.6) - typescript: 5.1.6 + ts-api-utils: 1.0.1(typescript@5.2.2) + typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@5.62.0(eslint@8.47.0)(typescript@5.1.6): - resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) - debug: 4.3.4 - eslint: 8.47.0 - typescript: 5.1.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@6.3.0(eslint@8.47.0)(typescript@5.1.6): - resolution: {integrity: sha512-ibP+y2Gr6p0qsUkhs7InMdXrwldjxZw66wpcQq9/PzAroM45wdwyu81T+7RibNCh8oc0AgrsyCwJByncY0Ongg==} + /@typescript-eslint/parser@6.9.0(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-GZmjMh4AJ/5gaH4XF2eXA8tMnHWP+Pm1mjQR2QN4Iz+j/zO04b9TOvJYOX2sCNIQHtRStKTxRY1FX7LhpJT4Gw==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -219,35 +198,27 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 6.3.0 - '@typescript-eslint/types': 6.3.0 - '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6) - '@typescript-eslint/visitor-keys': 6.3.0 + '@typescript-eslint/scope-manager': 6.9.0 + '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2) + '@typescript-eslint/visitor-keys': 6.9.0 debug: 4.3.4 - eslint: 8.47.0 - typescript: 5.1.6 + eslint: 8.52.0 + typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - - /@typescript-eslint/scope-manager@6.3.0: - resolution: {integrity: sha512-WlNFgBEuGu74ahrXzgefiz/QlVb+qg8KDTpknKwR7hMH+lQygWyx0CQFoUmMn1zDkQjTBBIn75IxtWss77iBIQ==} + /@typescript-eslint/scope-manager@6.9.0: + resolution: {integrity: sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==} engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 6.3.0 - '@typescript-eslint/visitor-keys': 6.3.0 + '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/visitor-keys': 6.9.0 dev: true - /@typescript-eslint/type-utils@6.3.0(eslint@8.47.0)(typescript@5.1.6): - resolution: {integrity: sha512-7Oj+1ox1T2Yc8PKpBvOKWhoI/4rWFd1j7FA/rPE0lbBPXTKjdbtC+7Ev0SeBjEKkIhKWVeZSP+mR7y1Db1CdfQ==} + /@typescript-eslint/type-utils@6.9.0(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -256,101 +227,71 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6) - '@typescript-eslint/utils': 6.3.0(eslint@8.47.0)(typescript@5.1.6) + '@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2) + '@typescript-eslint/utils': 6.9.0(eslint@8.52.0)(typescript@5.2.2) debug: 4.3.4 - eslint: 8.47.0 - ts-api-utils: 1.0.1(typescript@5.1.6) - typescript: 5.1.6 + eslint: 8.52.0 + ts-api-utils: 1.0.1(typescript@5.2.2) + typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@6.3.0: - resolution: {integrity: sha512-K6TZOvfVyc7MO9j60MkRNWyFSf86IbOatTKGrpTQnzarDZPYPVy0oe3myTMq7VjhfsUAbNUW8I5s+2lZvtx1gg==} + /@typescript-eslint/types@6.9.0: + resolution: {integrity: sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.1.6): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/typescript-estree@6.9.0(typescript@5.2.2): + resolution: {integrity: sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==} + engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 + '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/visitor-keys': 6.9.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - tsutils: 3.21.0(typescript@5.1.6) - typescript: 5.1.6 + ts-api-utils: 1.0.1(typescript@5.2.2) + typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/typescript-estree@6.3.0(typescript@5.1.6): - resolution: {integrity: sha512-Xh4NVDaC4eYKY4O3QGPuQNp5NxBAlEvNQYOqJquR2MePNxO11E5K3t5x4M4Mx53IZvtpW+mBxIT0s274fLUocg==} - engines: {node: ^16.0.0 || >=18.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 6.3.0 - '@typescript-eslint/visitor-keys': 6.3.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.5.4 - ts-api-utils: 1.0.1(typescript@5.1.6) - typescript: 5.1.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@6.3.0(eslint@8.47.0)(typescript@5.1.6): - resolution: {integrity: sha512-hLLg3BZE07XHnpzglNBG8P/IXq/ZVXraEbgY7FM0Cnc1ehM8RMdn9mat3LubJ3KBeYXXPxV1nugWbQPjGeJk6Q==} + /@typescript-eslint/utils@6.9.0(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 6.3.0 - '@typescript-eslint/types': 6.3.0 - '@typescript-eslint/typescript-estree': 6.3.0(typescript@5.1.6) - eslint: 8.47.0 + '@typescript-eslint/scope-manager': 6.9.0 + '@typescript-eslint/types': 6.9.0 + '@typescript-eslint/typescript-estree': 6.9.0(typescript@5.2.2) + eslint: 8.52.0 semver: 7.5.4 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@typescript-eslint/visitor-keys@6.9.0: + resolution: {integrity: sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==} + engines: {node: ^16.0.0 || >=18.0.0} dependencies: - '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/types': 6.9.0 eslint-visitor-keys: 3.4.3 dev: true - /@typescript-eslint/visitor-keys@6.3.0: - resolution: {integrity: sha512-kEhRRj7HnvaSjux1J9+7dBen15CdWmDnwrpyiHsFX6Qx2iW5LOBUgNefOFeh2PjWPlNwN8TOn6+4eBU3J/gupw==} - engines: {node: ^16.0.0 || >=18.0.0} - dependencies: - '@typescript-eslint/types': 6.3.0 - eslint-visitor-keys: 3.4.3 + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true /acorn-jsx@5.3.2(acorn@8.10.0): @@ -399,8 +340,8 @@ packages: is-array-buffer: 3.0.2 dev: true - /array-includes@3.1.6: - resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} + /array-includes@3.1.7: + resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 @@ -415,8 +356,8 @@ packages: engines: {node: '>=8'} dev: true - /array.prototype.findlastindex@1.2.2: - resolution: {integrity: sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==} + /array.prototype.findlastindex@1.2.3: + resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 @@ -426,8 +367,8 @@ packages: get-intrinsic: 1.2.1 dev: true - /array.prototype.flat@1.3.1: - resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} + /array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 @@ -436,8 +377,8 @@ packages: es-shim-unscopables: 1.0.0 dev: true - /array.prototype.flatmap@1.3.1: - resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} + /array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 @@ -703,38 +644,38 @@ packages: engines: {node: '>=10'} dev: true - /eslint-config-prettier@9.0.0(eslint@8.47.0): + /eslint-config-prettier@9.0.0(eslint@8.52.0): resolution: {integrity: sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.47.0 + eslint: 8.52.0 dev: true - /eslint-config-standard-with-typescript@37.0.0(@typescript-eslint/eslint-plugin@6.3.0)(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0)(typescript@5.1.6): - resolution: {integrity: sha512-V8I/Q1eFf9tiOuFHkbksUdWO3p1crFmewecfBtRxXdnvb71BCJx+1xAknlIRZMwZioMX3/bPtMVCZsf1+AjjOw==} + /eslint-config-standard-with-typescript@39.1.1(@typescript-eslint/eslint-plugin@6.9.0)(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0)(typescript@5.2.2): + resolution: {integrity: sha512-t6B5Ep8E4I18uuoYeYxINyqcXb2UbC0SOOTxRtBSt2JUs+EzeXbfe2oaiPs71AIdnoWhXDO2fYOHz8df3kV84A==} peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.52.0 + '@typescript-eslint/eslint-plugin': ^6.4.0 eslint: ^8.0.1 eslint-plugin-import: ^2.25.2 eslint-plugin-n: '^15.0.0 || ^16.0.0 ' eslint-plugin-promise: ^6.0.0 typescript: '*' dependencies: - '@typescript-eslint/eslint-plugin': 6.3.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0)(typescript@5.1.6) - '@typescript-eslint/parser': 5.62.0(eslint@8.47.0)(typescript@5.1.6) - eslint: 8.47.0 - eslint-config-standard: 17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0) - eslint-plugin-import: 2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0) - eslint-plugin-n: 16.0.1(eslint@8.47.0) - eslint-plugin-promise: 6.1.1(eslint@8.47.0) - typescript: 5.1.6 + '@typescript-eslint/eslint-plugin': 6.9.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + eslint: 8.52.0 + eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + eslint-plugin-n: 16.2.0(eslint@8.52.0) + eslint-plugin-promise: 6.1.1(eslint@8.52.0) + typescript: 5.2.2 transitivePeerDependencies: - supports-color dev: true - /eslint-config-standard@17.1.0(eslint-plugin-import@2.28.0)(eslint-plugin-n@16.0.1)(eslint-plugin-promise@6.1.1)(eslint@8.47.0): + /eslint-config-standard@17.1.0(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0): resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==} engines: {node: '>=12.0.0'} peerDependencies: @@ -743,23 +684,23 @@ packages: eslint-plugin-n: '^15.0.0 || ^16.0.0 ' eslint-plugin-promise: ^6.0.0 dependencies: - eslint: 8.47.0 - eslint-plugin-import: 2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0) - eslint-plugin-n: 16.0.1(eslint@8.47.0) - eslint-plugin-promise: 6.1.1(eslint@8.47.0) + eslint: 8.52.0 + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + eslint-plugin-n: 16.2.0(eslint@8.52.0) + eslint-plugin-promise: 6.1.1(eslint@8.52.0) dev: true /eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} dependencies: debug: 3.2.7 - is-core-module: 2.13.0 + is-core-module: 2.13.1 resolve: 1.22.4 transitivePeerDependencies: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.3.0)(eslint-import-resolver-node@0.3.9)(eslint@8.47.0): + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -780,27 +721,27 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.3.0(eslint@8.47.0)(typescript@5.1.6) + '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) debug: 3.2.7 - eslint: 8.47.0 + eslint: 8.52.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-es-x@7.2.0(eslint@8.47.0): + /eslint-plugin-es-x@7.2.0(eslint@8.52.0): resolution: {integrity: sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '>=8' dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) '@eslint-community/regexpp': 4.6.2 - eslint: 8.47.0 + eslint: 8.52.0 dev: true - /eslint-plugin-import@2.28.0(@typescript-eslint/parser@6.3.0)(eslint@8.47.0): - resolution: {integrity: sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==} + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0): + resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -809,24 +750,23 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 6.3.0(eslint@8.47.0)(typescript@5.1.6) - array-includes: 3.1.6 - array.prototype.findlastindex: 1.2.2 - array.prototype.flat: 1.3.1 - array.prototype.flatmap: 1.3.1 + '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) + array-includes: 3.1.7 + array.prototype.findlastindex: 1.2.3 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.47.0 + eslint: 8.52.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.3.0)(eslint-import-resolver-node@0.3.9)(eslint@8.47.0) - has: 1.0.3 - is-core-module: 2.13.0 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0) + hasown: 2.0.0 + is-core-module: 2.13.1 is-glob: 4.0.3 minimatch: 3.1.2 - object.fromentries: 2.0.6 - object.groupby: 1.0.0 - object.values: 1.1.6 - resolve: 1.22.4 + object.fromentries: 2.0.7 + object.groupby: 1.0.1 + object.values: 1.1.7 semver: 6.3.1 tsconfig-paths: 3.14.2 transitivePeerDependencies: @@ -835,16 +775,17 @@ packages: - supports-color dev: true - /eslint-plugin-n@16.0.1(eslint@8.47.0): - resolution: {integrity: sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==} + /eslint-plugin-n@16.2.0(eslint@8.52.0): + resolution: {integrity: sha512-AQER2jEyQOt1LG6JkGJCCIFotzmlcCZFur2wdKrp1JX2cNotC7Ae0BcD/4lLv3lUAArM9uNS8z/fsvXTd0L71g==} engines: {node: '>=16.0.0'} peerDependencies: eslint: '>=7.0.0' dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) builtins: 5.0.1 - eslint: 8.47.0 - eslint-plugin-es-x: 7.2.0(eslint@8.47.0) + eslint: 8.52.0 + eslint-plugin-es-x: 7.2.0(eslint@8.52.0) + get-tsconfig: 4.7.2 ignore: 5.2.4 is-core-module: 2.13.0 minimatch: 3.1.2 @@ -852,8 +793,8 @@ packages: semver: 7.5.4 dev: true - /eslint-plugin-prettier@5.0.0(eslint-config-prettier@9.0.0)(eslint@8.47.0)(prettier@3.0.1): - resolution: {integrity: sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==} + /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.0.0)(eslint@8.52.0)(prettier@3.0.3): + resolution: {integrity: sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -866,20 +807,20 @@ packages: eslint-config-prettier: optional: true dependencies: - eslint: 8.47.0 - eslint-config-prettier: 9.0.0(eslint@8.47.0) - prettier: 3.0.1 + eslint: 8.52.0 + eslint-config-prettier: 9.0.0(eslint@8.52.0) + prettier: 3.0.3 prettier-linter-helpers: 1.0.0 synckit: 0.8.5 dev: true - /eslint-plugin-promise@6.1.1(eslint@8.47.0): + /eslint-plugin-promise@6.1.1(eslint@8.52.0): resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - eslint: 8.47.0 + eslint: 8.52.0 dev: true /eslint-scope@7.2.2: @@ -895,18 +836,19 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint@8.47.0: - resolution: {integrity: sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==} + /eslint@8.52.0: + resolution: {integrity: sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.47.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) '@eslint-community/regexpp': 4.6.2 '@eslint/eslintrc': 2.1.2 - '@eslint/js': 8.47.0 - '@humanwhocodes/config-array': 0.11.10 + '@eslint/js': 8.52.0 + '@humanwhocodes/config-array': 0.11.13 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 @@ -1085,6 +1027,10 @@ packages: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + /function.prototype.name@1.1.5: resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} engines: {node: '>= 0.4'} @@ -1121,6 +1067,12 @@ packages: get-intrinsic: 1.2.1 dev: true + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1225,6 +1177,13 @@ packages: function-bind: 1.1.1 dev: true + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + /human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -1306,6 +1265,12 @@ packages: has: 1.0.3 dev: true + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + dev: true + /is-date-object@1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} @@ -1526,10 +1491,6 @@ packages: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: true - /natural-compare-lite@1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - dev: true - /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true @@ -1567,8 +1528,8 @@ packages: object-keys: 1.1.1 dev: true - /object.fromentries@2.0.6: - resolution: {integrity: sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==} + /object.fromentries@2.0.7: + resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 @@ -1576,8 +1537,8 @@ packages: es-abstract: 1.22.1 dev: true - /object.groupby@1.0.0: - resolution: {integrity: sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==} + /object.groupby@1.0.1: + resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} dependencies: call-bind: 1.0.2 define-properties: 1.2.0 @@ -1585,8 +1546,8 @@ packages: get-intrinsic: 1.2.1 dev: true - /object.values@1.1.6: - resolution: {integrity: sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==} + /object.values@1.1.7: + resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 @@ -1707,18 +1668,18 @@ packages: fast-diff: 1.3.0 dev: true - /prettier-plugin-go-template@0.0.15(prettier@3.0.1): + /prettier-plugin-go-template@0.0.15(prettier@3.0.3): resolution: {integrity: sha512-WqU92E1NokWYNZ9mLE6ijoRg6LtIGdLMePt2C7UBDjXeDH9okcRI3zRqtnWR4s5AloiqyvZ66jNBAa9tmRY5EQ==} engines: {node: '>=14.0.0'} peerDependencies: prettier: ^3.0.0 dependencies: - prettier: 3.0.1 + prettier: 3.0.3 ulid: 2.3.0 dev: true - /prettier@3.0.1: - resolution: {integrity: sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==} + /prettier@3.0.3: + resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} engines: {node: '>=14'} hasBin: true dev: true @@ -1746,6 +1707,10 @@ packages: engines: {node: '>=4'} dev: true + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + /resolve@1.22.4: resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} hasBin: true @@ -1928,13 +1893,13 @@ packages: is-number: 7.0.0 dev: true - /ts-api-utils@1.0.1(typescript@5.1.6): + /ts-api-utils@1.0.1(typescript@5.2.2): resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==} engines: {node: '>=16.13.0'} peerDependencies: typescript: '>=4.2.0' dependencies: - typescript: 5.1.6 + typescript: 5.2.2 dev: true /tsconfig-paths@3.14.2: @@ -1946,24 +1911,10 @@ packages: strip-bom: 3.0.0 dev: true - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - /tslib@2.6.1: resolution: {integrity: sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==} dev: true - /tsutils@3.21.0(typescript@5.1.6): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.1.6 - dev: true - /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2014,8 +1965,8 @@ packages: is-typed-array: 1.1.12 dev: true - /typescript@5.1.6: - resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} + /typescript@5.2.2: + resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} engines: {node: '>=14.17'} hasBin: true dev: true From 6848e413caef4f43284bd10cd946775416952379 Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 14:54:52 +0800 Subject: [PATCH 05/13] chore(utils.ts): add custom helpers and types for better code organization and reusability --- assets/ts/utils.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/assets/ts/utils.ts b/assets/ts/utils.ts index e2e21e7..9717d03 100644 --- a/assets/ts/utils.ts +++ b/assets/ts/utils.ts @@ -1,3 +1,7 @@ +/** + * custom helpers + */ + export function increment(num: number, length: number): number { return (num + 1) % length } @@ -14,6 +18,14 @@ export function isMobile(): boolean { return window.matchMedia('(hover: none)').matches } +export function getRandom(min: number, max: number) { + return Math.floor(Math.random() * (max - min + 1)) + min +} + +/** + * custom types + */ + export class Watchable { constructor(private obj: T) {} private watchers: (() => void)[] = [] From 2025a57ae4a29493fb75882099229ce849dd615f Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 15:09:10 +0800 Subject: [PATCH 06/13] fix(customCursor.ts): fix variable declaration and initialization for cursor and cursorInner to improve code readability and maintainability feat(customCursor.ts): add support for setting custom text for cursorInner to display different cursor text fix(stage.ts): fix variable declaration and initialization for imgs, last, cordHist, isOpen, isAnimating, and active to improve code readability and maintainability feat(stage.ts): add support for minimizing image and initialize stage with image JSON data fix(stageNav.ts): fix variable declaration and initialization for navItems to improve code readability and maintainability feat(stageNav.ts): add support for handling click and key events for stage navigation fix(nav.ts): fix variable declaration and initialization for thresholdDiv and indexDispNums to improve code readability and maintainability feat(nav.ts): initialize nav and update threshold text --- assets/ts/desktop/customCursor.ts | 34 +++++++++++++++++++------------ assets/ts/desktop/stage.ts | 24 ++++++++++++++++------ assets/ts/desktop/stageNav.ts | 21 ++++++++++++++++--- assets/ts/nav.ts | 8 ++++++++ 4 files changed, 65 insertions(+), 22 deletions(-) diff --git a/assets/ts/desktop/customCursor.ts b/assets/ts/desktop/customCursor.ts index 030e1a2..ab67c99 100644 --- a/assets/ts/desktop/customCursor.ts +++ b/assets/ts/desktop/customCursor.ts @@ -1,16 +1,15 @@ import { active } from './stage' -let cursor: HTMLDivElement +/** + * variables + */ -// create cursor -cursor = document.createElement('div') -cursor.className = 'cursor' -cursor.classList.add('active') -// create cursor inner +const cursor = document.createElement('div') const cursorInner = document.createElement('div') -cursorInner.className = 'cursorInner' -// append cursor inner to cursor -cursor.append(cursorInner) + +/** + * main functions + */ function onMouse(e: MouseEvent) { const x = e.clientX @@ -18,7 +17,20 @@ function onMouse(e: MouseEvent) { cursor.style.transform = `translate3d(${x}px, ${y}px, 0)` } +export function setCustomCursor(text: string): void { + cursorInner.innerText = text +} + +/** + * init + */ export function initCustomCursor(): void { + // cursor class name + cursor.className = 'cursor' + // cursor inner class name + cursorInner.className = 'cursorInner' + // append cursor inner to cursor + cursor.append(cursorInner) // append cursor to main document.getElementById('main')!.append(cursor) // bind mousemove event to window @@ -32,7 +44,3 @@ export function initCustomCursor(): void { } }) } - -export function setCustomCursor(text: string): void { - cursorInner.innerText = text -} diff --git a/assets/ts/desktop/stage.ts b/assets/ts/desktop/stage.ts index 94405e4..1598251 100644 --- a/assets/ts/desktop/stage.ts +++ b/assets/ts/desktop/stage.ts @@ -3,11 +3,15 @@ import { gsap, Power3 } from 'gsap' import { ImageJSON } from '../resources' import { Watchable } from '../utils' -// types +/** + * types + */ export type HistoryItem = { i: number; x: number; y: number } -// variables +/** + * variables + */ let imgs: HTMLImageElement[] = [] let last = { x: 0, y: 0 } @@ -16,7 +20,9 @@ export const isOpen = new Watchable(false) export const isAnimating = new Watchable(false) export const active = new Watchable(false) -// getter +/** + * getter + */ function getElTrail(): HTMLImageElement[] { return cordHist.get().map((item) => imgs[item.i]) @@ -36,7 +42,9 @@ function getElCurrent(): HTMLImageElement { return elTrail[elTrail.length - 1] } -// main functions +/** + * main functions + */ // on mouse function onMouse(e: MouseEvent): void { @@ -146,7 +154,9 @@ export function minimizeImage(): void { }) } -// init +/** + * init + */ export function initStage(ijs: ImageJSON[]): void { // create stage element @@ -165,7 +175,9 @@ export function initStage(ijs: ImageJSON[]): void { cordHist.addWatcher(() => setPositions()) } -// hepler +/** + * hepler + */ function createStage(ijs: ImageJSON[]): void { // create container for images diff --git a/assets/ts/desktop/stageNav.ts b/assets/ts/desktop/stageNav.ts index 6d98c2c..7b60c6a 100644 --- a/assets/ts/desktop/stageNav.ts +++ b/assets/ts/desktop/stageNav.ts @@ -3,10 +3,21 @@ import { decIndex, incIndex, getState } from '../state' import { increment, decrement } from '../utils' import { cordHist, isOpen, isAnimating, active, minimizeImage } from './stage' +/** + * types + */ + type NavItem = (typeof navItems)[number] + +/** + * variables + */ + const navItems = ['prev', 'close', 'next'] as const -// main functions +/** + * main functions + */ function handleClick(type: NavItem) { switch (type) { @@ -37,7 +48,9 @@ function handleKey(e: KeyboardEvent) { } } -// init +/** + * init + */ export function initStageNav() { const navOverlay = document.createElement('div') @@ -62,7 +75,9 @@ export function initStageNav() { window.addEventListener('keydown', handleKey) } -// hepler +/** + * hepler + */ function nextImage() { if (isAnimating.get()) return diff --git a/assets/ts/nav.ts b/assets/ts/nav.ts index 6a8b235..833aa7e 100644 --- a/assets/ts/nav.ts +++ b/assets/ts/nav.ts @@ -1,6 +1,10 @@ import { getState, incThreshold, decThreshold } from './state' import { expand } from './utils' +/** + * variables + */ + // threshold div const thresholdDiv = document .getElementsByClassName('threshold') @@ -27,6 +31,10 @@ const indexDispNums = Array.from( indexDiv.getElementsByClassName('num') ) as HTMLSpanElement[] +/** + * init + */ + export function initNav() { // init threshold text updateThresholdText() From f3b5642f16462d3bc0d49bfc30e7a01c6390836d Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 22:08:26 +0800 Subject: [PATCH 07/13] chore(eslint): update eslint configuration to include recommended rules and plugins - Add "eslint:recommended" and "plugin:prettier/recommended" to the "extends" array to include recommended rules and prettier plugin. - Add "plugin:@typescript-eslint/recommended" to the "extends" array to include recommended rules for TypeScript. - Add "@typescript-eslint" and "prettier" to the "plugins" array to enable TypeScript and prettier linting. - Update "parserOptions" to use the latest ECMAScript version and specify the project path. - Add "sort-imports" rule to sort imports in a specific order and ignore case. - Add "import/no-unresolved" rule to enforce resolving of imports. - Add "import/order" rule to enforce a specific order for imports. - Update "settings" to specify the TypeScript project path for import resolver. chore(prettier): update prettier configuration to include additional plugins - Add "prettier-plugin-organize-imports" to the "plugins" array to enable organizing imports. - Update "overrides" to include "*.html" files for prettier formatting. feat(package.json): add "swiper" dependency - Add "swiper" dependency with version "^11.0.3" to the "dependencies" section. --- .eslintrc.json | 69 ++++++++++++++++++++++++++++----------- .prettierrc.json | 2 +- package.json | 5 ++- pnpm-lock.yaml | 84 ++++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 133 insertions(+), 27 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 122076d..222d475 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,23 +1,54 @@ { - "env": { - "browser": true, - "es2021": true - }, - "extends": [ - "standard-with-typescript", - "prettier" + "env": { + "browser": true, + "es2021": true + }, + "extends": [ + "standard-with-typescript", + "prettier", + "eslint:recommended", + "plugin:prettier/recommended", + "plugin:@typescript-eslint/recommended" + ], + "overrides": [], + "plugins": ["prettier", "@typescript-eslint"], + "parserOptions": { + "ecmaVersion": "latest", + "project": "./tsconfig.json", + "sourceType": "module" + }, + "rules": { + "prettier/prettier": "error", + "arrow-body-style": "off", + "prefer-arrow-callback": "off", + "sort-imports": [ + "error", + { + "ignoreCase": false, + "ignoreDeclarationSort": true, + "ignoreMemberSort": false, + "memberSyntaxSortOrder": ["none", "all", "multiple", "single"], + "allowSeparatedGroups": true + } ], - "overrides": [ - ], - "plugins": ["prettier"], - "parserOptions": { - "ecmaVersion": "latest", - "project": "./tsconfig.json", - "sourceType": "module" - }, - "rules": { - "prettier/prettier": "error", - "arrow-body-style": "off", - "prefer-arrow-callback": "off" + "import/no-unresolved": "error", + "import/order": [ + "error", + { + "groups": ["builtin", "external", "internal", "parent", "sibling", "index"], + "newlines-between": "always", + "alphabetize": { + "order": "asc", + "caseInsensitive": true + } + } + ] + }, + "settings": { + "import/resolver": { + "typescript": { + "project": "./tsconfig.json" + } } + } } diff --git a/.prettierrc.json b/.prettierrc.json index 263da8b..78d451e 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -6,7 +6,7 @@ "trailingComma": "none", "bracketSpacing": true, "semi": false, - "plugins": ["prettier-plugin-go-template"], + "plugins": ["prettier-plugin-go-template", "prettier-plugin-organize-imports"], "overrides": [ { "files": ["*.html"], diff --git a/package.json b/package.json index 99b5cf5..e5696c1 100644 --- a/package.json +++ b/package.json @@ -32,15 +32,18 @@ "eslint-config-prettier": "^9.0.0", "eslint-config-standard": "^17.1.0", "eslint-config-standard-with-typescript": "^39.1.1", + "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.0", "eslint-plugin-n": "^16.2.0", "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-promise": "^6.1.1", "prettier": "3.0.3", "prettier-plugin-go-template": "^0.0.15", + "prettier-plugin-organize-imports": "^3.2.3", "typescript": "^5.2.2" }, "dependencies": { - "gsap": "^3.12.2" + "gsap": "^3.12.2", + "swiper": "^11.0.3" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7ad210..762beac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: gsap: specifier: ^3.12.2 version: 3.12.2 + swiper: + specifier: ^11.0.3 + version: 11.0.3 devDependencies: '@typescript-eslint/eslint-plugin': @@ -28,9 +31,12 @@ devDependencies: eslint-config-standard-with-typescript: specifier: ^39.1.1 version: 39.1.1(@typescript-eslint/eslint-plugin@6.9.0)(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0)(typescript@5.2.2) + eslint-import-resolver-typescript: + specifier: ^3.6.1 + version: 3.6.1(@typescript-eslint/parser@6.9.0)(eslint-plugin-import@2.29.0)(eslint@8.52.0) eslint-plugin-import: specifier: ^2.29.0 - version: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + version: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) eslint-plugin-n: specifier: ^16.2.0 version: 16.2.0(eslint@8.52.0) @@ -46,6 +52,9 @@ devDependencies: prettier-plugin-go-template: specifier: ^0.0.15 version: 0.0.15(prettier@3.0.3) + prettier-plugin-organize-imports: + specifier: ^3.2.3 + version: 3.2.3(prettier@3.0.3)(typescript@5.2.2) typescript: specifier: ^5.2.2 version: 5.2.2 @@ -570,6 +579,14 @@ packages: esutils: 2.0.3 dev: true + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + /es-abstract@1.22.1: resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} engines: {node: '>= 0.4'} @@ -667,7 +684,7 @@ packages: '@typescript-eslint/parser': 6.9.0(eslint@8.52.0)(typescript@5.2.2) eslint: 8.52.0 eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.0)(eslint-plugin-n@16.2.0)(eslint-plugin-promise@6.1.1)(eslint@8.52.0) - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) eslint-plugin-n: 16.2.0(eslint@8.52.0) eslint-plugin-promise: 6.1.1(eslint@8.52.0) typescript: 5.2.2 @@ -685,7 +702,7 @@ packages: eslint-plugin-promise: ^6.0.0 dependencies: eslint: 8.52.0 - eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) eslint-plugin-n: 16.2.0(eslint@8.52.0) eslint-plugin-promise: 6.1.1(eslint@8.52.0) dev: true @@ -700,7 +717,30 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0): + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.9.0)(eslint-plugin-import@2.29.0)(eslint@8.52.0): + resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4 + enhanced-resolve: 5.15.0 + eslint: 8.52.0 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) + eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) + fast-glob: 3.3.1 + get-tsconfig: 4.7.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0): resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} engines: {node: '>=4'} peerDependencies: @@ -725,6 +765,7 @@ packages: debug: 3.2.7 eslint: 8.52.0 eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.9.0)(eslint-plugin-import@2.29.0)(eslint@8.52.0) transitivePeerDependencies: - supports-color dev: true @@ -740,7 +781,7 @@ packages: eslint: 8.52.0 dev: true - /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.9.0)(eslint@8.52.0): + /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0): resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} engines: {node: '>=4'} peerDependencies: @@ -759,7 +800,7 @@ packages: doctrine: 2.1.0 eslint: 8.52.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint@8.52.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -1130,6 +1171,10 @@ packages: get-intrinsic: 1.2.1 dev: true + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true @@ -1678,6 +1723,23 @@ packages: ulid: 2.3.0 dev: true + /prettier-plugin-organize-imports@3.2.3(prettier@3.0.3)(typescript@5.2.2): + resolution: {integrity: sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg==} + peerDependencies: + '@volar/vue-language-plugin-pug': ^1.0.4 + '@volar/vue-typescript': ^1.0.4 + prettier: '>=2.0' + typescript: '>=2.9' + peerDependenciesMeta: + '@volar/vue-language-plugin-pug': + optional: true + '@volar/vue-typescript': + optional: true + dependencies: + prettier: 3.0.3 + typescript: 5.2.2 + dev: true + /prettier@3.0.3: resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} engines: {node: '>=14'} @@ -1869,6 +1931,11 @@ packages: engines: {node: '>= 0.4'} dev: true + /swiper@11.0.3: + resolution: {integrity: sha512-MyV9ooQsriAe2EibeamqewLjgCfSvl2xoyratl6S3ln5BXDL4BzlO6mxcbLMCzQL6Z60b/u0AS/nKrepL0+TAg==} + engines: {node: '>= 4.7.0'} + dev: false + /synckit@0.8.5: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} engines: {node: ^14.18.0 || >=16.0.0} @@ -1877,6 +1944,11 @@ packages: tslib: 2.6.1 dev: true + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true From ca4f2d2902be95d251f88f1d3f48b78548c955ad Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 22:09:36 +0800 Subject: [PATCH 08/13] feat(scss): add core base styles Add a new file `_base.scss` to the `_core` directory. This file contains base styles for the entire application. The styles include setting font smoothing properties, setting the background color of the body, and disabling overscroll behavior on the html and body elements. Additionally, the styles set the cursor property to pointer for anchor tags and buttons. feat(scss): add core font styles Add a new file `_font.scss` to the `_core` directory. This file defines the `HelveticaNow` font face and specifies the font weight and style. feat(scss): add core mixins Add a new file `_mixins.scss` to the `_core` directory. This file defines mixins for working with breakpoints. The mixins allow for specifying styles based on minimum and maximum widths of breakpoints defined in the `$breakpoints` map. feat(scss): add core typography styles Add a new file `_typography.scss` to the `_core` directory. This file defines typography styles for the body element. The styles set the line height, font size, and font family. Additionally, the styles use the `min-width` mixin to increase the font size at tablet and laptop breakpoints. feat(scss): add partial customCursor styles Add a new file `_customCursor.scss` to the `_partial` directory. This file defines styles for a custom cursor. The styles position the cursor element, set its color and blend mode, and define an inner element for the cursor. feat(scss): add partial stage styles Add a new file `_stage.scss` to the `_partial` directory. This file defines styles for a stage element. The styles position the stage element, set its width and height, and define styles for an image element within the stage. feat(scss): add partial stageNav styles Add a new file `_stageNav.scss` to the `_partial` directory. This file defines styles for a stage navigation overlay. The styles position the overlay element and set its width and height. The styles also define an inactive state for the overlay. feat(scss): add variables Add a new file `_variables.scss` to the root directory. This file defines CSS variables for various aspects of the application, such as window height, navigation height, spacing, and z-index values. feat(scss): import styles in main style.scss Add import statements for the newly created files in the `style.scss` file. This ensures that the --- assets/{css => scss}/_core/_base.scss | 0 assets/{css => scss}/_core/_font.scss | 0 assets/{css => scss}/_core/_mixins.scss | 0 assets/{css => scss}/_core/_typography.scss | 0 assets/{css => scss}/_partial/_customCursor.scss | 8 ++++---- assets/{css => scss}/_partial/_stage.scss | 0 assets/{css => scss}/_partial/_stageNav.scss | 0 assets/{css => scss}/_variables.scss | 0 assets/{css => scss}/style.scss | 6 +++++- 9 files changed, 9 insertions(+), 5 deletions(-) rename assets/{css => scss}/_core/_base.scss (100%) rename assets/{css => scss}/_core/_font.scss (100%) rename assets/{css => scss}/_core/_mixins.scss (100%) rename assets/{css => scss}/_core/_typography.scss (100%) rename assets/{css => scss}/_partial/_customCursor.scss (77%) rename assets/{css => scss}/_partial/_stage.scss (100%) rename assets/{css => scss}/_partial/_stageNav.scss (100%) rename assets/{css => scss}/_variables.scss (100%) rename assets/{css => scss}/style.scss (81%) diff --git a/assets/css/_core/_base.scss b/assets/scss/_core/_base.scss similarity index 100% rename from assets/css/_core/_base.scss rename to assets/scss/_core/_base.scss diff --git a/assets/css/_core/_font.scss b/assets/scss/_core/_font.scss similarity index 100% rename from assets/css/_core/_font.scss rename to assets/scss/_core/_font.scss diff --git a/assets/css/_core/_mixins.scss b/assets/scss/_core/_mixins.scss similarity index 100% rename from assets/css/_core/_mixins.scss rename to assets/scss/_core/_mixins.scss diff --git a/assets/css/_core/_typography.scss b/assets/scss/_core/_typography.scss similarity index 100% rename from assets/css/_core/_typography.scss rename to assets/scss/_core/_typography.scss diff --git a/assets/css/_partial/_customCursor.scss b/assets/scss/_partial/_customCursor.scss similarity index 77% rename from assets/css/_partial/_customCursor.scss rename to assets/scss/_partial/_customCursor.scss index 591c8f5..7324d33 100644 --- a/assets/css/_partial/_customCursor.scss +++ b/assets/scss/_partial/_customCursor.scss @@ -10,12 +10,12 @@ color: white; mix-blend-mode: difference; + + .cursorInner { + transform: translate3d(-50%, -50%, 0); + } } .active { display: block; } - -.cursorInner { - transform: translate3d(-50%, -50%, 0); -} diff --git a/assets/css/_partial/_stage.scss b/assets/scss/_partial/_stage.scss similarity index 100% rename from assets/css/_partial/_stage.scss rename to assets/scss/_partial/_stage.scss diff --git a/assets/css/_partial/_stageNav.scss b/assets/scss/_partial/_stageNav.scss similarity index 100% rename from assets/css/_partial/_stageNav.scss rename to assets/scss/_partial/_stageNav.scss diff --git a/assets/css/_variables.scss b/assets/scss/_variables.scss similarity index 100% rename from assets/css/_variables.scss rename to assets/scss/_variables.scss diff --git a/assets/css/style.scss b/assets/scss/style.scss similarity index 81% rename from assets/css/style.scss rename to assets/scss/style.scss index 96c8842..8e8e9e8 100644 --- a/assets/css/style.scss +++ b/assets/scss/style.scss @@ -7,7 +7,11 @@ @import '_variables'; @import '_core/base'; -@import '_partial/customCursor'; @import '_partial/nav'; + +@import '_partial/customCursor'; @import '_partial/stage'; @import '_partial/stageNav'; + +@import '_partial/collection'; +@import '_partial/gallery'; From 2e3fc3d7b63555d865c8351e0ab7656d7af92bc1 Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 22:10:02 +0800 Subject: [PATCH 09/13] feat(reset.scss): add new CSS reset file to reset default styles and improve cross-browser consistency The new CSS reset file is added to the project. This file is used to reset default styles applied by the user agent stylesheet and provide a clean starting point for styling. The reset file includes various CSS rules to remove default styles and improve cross-browser consistency. Some of the changes made in the reset.scss file include: - Removing all styles of the "User-Agent-Stylesheet" except for the 'display' property to solve Firefox SVG sprite bug and prevent a bug in Chrome that breaks the CSS hyphens property. - Setting the box-sizing property to border-box for all elements and pseudo-elements to ensure consistent box sizing. - Fixing the increase in font-size on mobile Safari in landscape mode. - Reapplying the pointer cursor for anchor tags and buttons. - Removing list styles (bullets/numbers) from ordered lists, unordered lists, menus, and summary elements. - Setting max-inline-size and max-block-size properties to 100% for images to prevent them from exceeding their container. - Removing spacing between cells in tables. - Fixing an issue in Safari where the user-select:none property doesn't work on the text input. - Reverting the 'white-space' property for textarea elements on Safari. - Applying minimum styles to allow styling of the meter element. - Reverting all styles for preformatted text. - Resetting the default text opacity of input placeholders. - Fixing the 'hidden' attribute to use display: none instead of the attribute itself. - Fixing a bug in Chromium browsers where the content editable attribute doesn't work properly. - Applying the draggable feature for elements with the draggable attribute set to 'true'. - Reverting the native behavior of modal dialogs. These changes are made to ensure a consistent and predictable starting point for styling in the project and improve cross-browser compatibility. --- assets/{css => scss}/_core/_reset.scss | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) rename assets/{css => scss}/_core/_reset.scss (82%) diff --git a/assets/css/_core/_reset.scss b/assets/scss/_core/_reset.scss similarity index 82% rename from assets/css/_core/_reset.scss rename to assets/scss/_core/_reset.scss index 0de3854..4070fab 100644 --- a/assets/css/_core/_reset.scss +++ b/assets/scss/_core/_reset.scss @@ -1,11 +1,12 @@ /*** - The new CSS reset - version 1.8.4 (last updated 14.2.2023) + The new CSS reset - version 1.11.1 (last updated 24.10.2023) GitHub page: https://github.com/elad2412/the-new-css-reset ***/ /* Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property - The "symbol *" part is to solve Firefox SVG sprite bug + - The "html" element is excluded, otherwise a bug in Chrome breaks the CSS hyphens property (https://github.com/elad2412/the-new-css-reset/issues/36) */ *:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) { all: unset; @@ -19,6 +20,13 @@ box-sizing: border-box; } +/* Fix mobile Safari increase font-size on landscape mode */ +html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; +} + /* Reapply the pointer cursor for anchor tags */ a, button { @@ -28,7 +36,8 @@ button { /* Remove list styles (bullets/numbers) */ ol, ul, -menu { +menu, +summary { list-style: none; } @@ -63,6 +72,7 @@ meter { /* preformatted text - use only for this feature */ :where(pre) { all: revert; + box-sizing: border-box; } /* reset default text opacity of input placeholder */ @@ -70,11 +80,6 @@ meter { color: unset; } -/* remove default dot (•) sign */ -::marker { - content: initial; -} - /* fix the feature of 'hidden' attribute. display:revert; revert to element instead of attribute */ :where([hidden]) { @@ -100,4 +105,5 @@ meter { /* Revert Modal native behavior */ :where(dialog:modal) { all: revert; + box-sizing: border-box; } From bd2354e2f57a58a608ab1cd1a88e9a5a3d1997ac Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 22:11:04 +0800 Subject: [PATCH 10/13] feat: add new SCSS partials for collection and gallery components - Added a new SCSS partial `_collection.scss` to define styles for the collection component. - Added a new SCSS partial `_gallery.scss` to define styles for the gallery component. The new partials contain styles for the collection and gallery components, including layout, positioning, and animations. --- feat: add support for gallery functionality in mobile - Created a new file `gallery.ts` to handle the gallery functionality in the mobile view. - Added functions `slideUp()` and `slideDown()` to handle the sliding animation of the gallery. - Initialized the gallery with the provided image data in the `initGallery()` function. - Added event listeners to update the active slide and index text when the slide is changed. - Created a helper function `changeSlide()` to change the active slide in the gallery. - Created a helper function `scrollToActive()` to scroll to the active image in the collection. - Created a helper function `updateIndexText()` to update the index text in the navigation. - Created a helper function `createGallery()` to dynamically create the gallery HTML structure. --- feat: add scrollable flag for mobile view - Created a new file `scroll.ts` to handle the scrollable flag for the mobile view. - Added a `scrollable` variable as a Watchable object to control the scrollability of the view. --- fix: change port variable case from lowercase `port` to uppercase `PORT` to improve semantics - Changed the variable name `port` to `PORT` in the `server.ts` file to improve code readability and semantics. - The variable `PORT` is now used to define the port number for the server to listen on. --- assets/scss/_partial/_collection.scss | 29 ++++ assets/scss/_partial/_gallery.scss | 56 ++++++++ assets/ts/mobile/collection.ts | 73 ++++++++++ assets/ts/mobile/gallery.ts | 198 ++++++++++++++++++++++++++ assets/ts/mobile/scroll.ts | 3 + layouts/partials/head.html | 6 +- 6 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 assets/scss/_partial/_collection.scss create mode 100644 assets/scss/_partial/_gallery.scss create mode 100644 assets/ts/mobile/gallery.ts create mode 100644 assets/ts/mobile/scroll.ts diff --git a/assets/scss/_partial/_collection.scss b/assets/scss/_partial/_collection.scss new file mode 100644 index 0000000..ec63f67 --- /dev/null +++ b/assets/scss/_partial/_collection.scss @@ -0,0 +1,29 @@ +.collection { + display: flex; + flex-direction: column; + gap: 20vh; + + padding-top: 50vh; + margin-top: calc(var(--nav-height) * -1); + + img { + position: sticky; + top: 50vh; + + width: 60vw; + height: 20vh; + + object-fit: contain; + + transform: translate3d(0, -50%, 0); + align-self: center; + + &:last-child { + margin-bottom: 20vh; + } + } +} + +.hidden { + display: none; +} diff --git a/assets/scss/_partial/_gallery.scss b/assets/scss/_partial/_gallery.scss new file mode 100644 index 0000000..1d82815 --- /dev/null +++ b/assets/scss/_partial/_gallery.scss @@ -0,0 +1,56 @@ +.gallery { + pointer-events: all; + + position: fixed; + top: var(--nav-height); + z-index: var(--z-nav-gallery); + + display: flex; + flex-direction: column; + + width: 100vw; + height: calc(var(--window-height) - var(--nav-height)); + background: white; + transform: translate3d(0, 100%, 0); + + .galleryInner { + flex: 1; + height: 0; + + .swiper-slide { + display: flex; + align-items: center; + justify-content: center; + + img { + width: 100%; + height: 100%; + object-fit: contain; + } + } + } + + .nav { + height: var(--nav-height); + padding: var(--space-standard); + + display: flex; + justify-content: space-between; + align-items: center; + } +} + +.curtain { + position: fixed; + top: 0; + left: 0; + z-index: var(--z-curtain); + + width: 100vw; + height: var(--window-height); + + background: rgba(0, 0, 0, 0.5); + opacity: 0; + + pointer-events: none; +} diff --git a/assets/ts/mobile/collection.ts b/assets/ts/mobile/collection.ts index e69de29..a661bc2 100644 --- a/assets/ts/mobile/collection.ts +++ b/assets/ts/mobile/collection.ts @@ -0,0 +1,73 @@ +import { container } from '../container' +import { ImageJSON } from '../resources' +import { setIndex } from '../state' +import { getRandom, Watchable } from '../utils' +import { slideUp } from './gallery' + +/** + * variables + */ + +export let imgs: HTMLImageElement[] = [] +export const mounted = new Watchable(false) + +/** + * main functions + */ + +function handleClick(i: number): void { + setIndex(i) + slideUp() +} + +/** + * init + */ + +export function initCollection(ijs: ImageJSON[]): void { + createCollection(ijs) + // get container + const container = document + .getElementsByClassName('collection') + .item(0) as HTMLDivElement + // add watcher + mounted.addWatcher(() => { + if (mounted.get()) { + container.classList.remove('hidden') + } else { + container.classList.add('hidden') + } + }) + // get image elements + imgs = Array.from(container.getElementsByTagName('img')) + // add event listeners + imgs.forEach((img, i) => { + img.addEventListener('click', () => handleClick(i)) + img.addEventListener('keydown', () => handleClick(i)) + }) +} + +/** + * helper + */ + +function createCollection(ijs: ImageJSON[]): void { + // create container for images + const collection: HTMLDivElement = document.createElement('div') + collection.className = 'collection' + // append images to container + for (let [i, ij] of ijs.entries()) { + // random x and y + const x = i !== 0 ? getRandom(-25, 25) : 0 + const y = i !== 0 ? getRandom(-30, 30) : 0 + // element + const e = document.createElement('img') + e.src = ij.url + e.height = ij.imgH + e.width = ij.imgW + e.alt = 'image' + e.style.transform = `translate3d(${x}%, ${y - 50}%, 0)` + collection.append(e) + } + container.append(collection) +} diff --git a/assets/ts/mobile/gallery.ts b/assets/ts/mobile/gallery.ts new file mode 100644 index 0000000..a9167ae --- /dev/null +++ b/assets/ts/mobile/gallery.ts @@ -0,0 +1,198 @@ +import { Power3, gsap } from 'gsap' +import Swiper from 'swiper' +import { container } from '../container' +import { ImageJSON } from '../resources' +import { setIndex, state } from '../state' +import { Watchable, expand } from '../utils' +import { imgs, mounted } from './collection' +import { scrollable } from './scroll' + +/** + * variables + */ + +let swiperNode: HTMLDivElement +let gallery: HTMLDivElement +let curtain: HTMLDivElement +let swiper: Swiper +const isAnimating = new Watchable(false) +let lastIndex = -1 +let indexDispNums: HTMLSpanElement[] = [] + +/** + * main functions + */ + +export function slideUp(): void { + if (isAnimating.get()) return + isAnimating.set(true) + + gsap.to(curtain, { + opacity: 1, + duration: 1 + }) + + gsap.to(gallery, { + y: 0, + ease: Power3.easeInOut, + duration: 1, + delay: 0.4 + }) + + setTimeout(() => { + scrollable.set(false) + isAnimating.set(false) + }, 1200) +} + +function slideDown(): void { + scrollable.set(true) + scrollToActive() + + gsap.to(gallery, { + y: '100%', + ease: Power3.easeInOut, + duration: 1 + }) + + gsap.to(curtain, { + opacity: 0, + duration: 1.2, + delay: 0.4 + }) +} + +/** + * init + */ + +export function initGallery(ijs: ImageJSON[]): void { + // create gallery + createGallery(ijs) + // get elements + indexDispNums = Array.from( + document.getElementsByClassName('nav').item(0)!.getElementsByClassName('num') + ) as HTMLSpanElement[] + swiperNode = document.getElementsByClassName('galleryInner').item(0) as HTMLDivElement + gallery = document.getElementsByClassName('gallery').item(0) as HTMLDivElement + curtain = document.getElementsByClassName('curtain').item(0) as HTMLDivElement + // state watcher + state.addWatcher(() => { + const s = state.get() + // change slide only when index is changed + if (s.index === lastIndex) return + changeSlide(s.index) + updateIndexText() + lastIndex = s.index + }) + // mounted watcher + mounted.addWatcher(() => { + if (!mounted.get()) return + scrollable.set(true) + swiper = new Swiper(swiperNode, { spaceBetween: 20 }) + swiper.on('slideChange', ({ realIndex }) => { + setIndex(realIndex) + }) + }) + + // mounted + mounted.set(true) +} + +/** + * helper + */ + +function changeSlide(slide: number): void { + console.log(slide) + swiper?.slideTo(slide, 0) +} + +function scrollToActive(): void { + imgs[state.get().index].scrollIntoView({ + block: 'center', + behavior: 'auto' + }) +} + +function updateIndexText(): void { + const indexValue: string = expand(state.get().index + 1) + const indexLength: string = expand(state.get().length) + indexDispNums.forEach((e: HTMLSpanElement, i: number) => { + if (i < 4) { + e.innerText = indexValue[i] + } else { + e.innerText = indexLength[i - 4] + } + }) +} + +function createGallery(ijs: ImageJSON[]): void { + /** + * gallery + * |- galleryInner + * |- swiper-wrapper + * |- swiper-slide + * |- img + * |- swiper-slide + * |- img + * |- ... + * |- nav + * |- index + * |- close + */ + // swiper wrapper + const _swiperWrapper = document.createElement('div') + _swiperWrapper.className = 'swiper-wrapper' + // swiper slide + for (let ij of ijs) { + const _swiperSlide = document.createElement('div') + _swiperSlide.className = 'swiper-slide' + // img + const e = document.createElement('img') + e.src = ij.url + e.alt = 'image' + // append + _swiperSlide.append(e) + _swiperWrapper.append(_swiperSlide) + } + // swiper node + const _swiperNode = document.createElement('div') + _swiperNode.className = 'galleryInner' + _swiperNode.append(_swiperWrapper) + // index + const _index = document.createElement('div') + _index.insertAdjacentHTML( + 'afterbegin', + ` + / + ` + ) + // close + const _close = document.createElement('div') + _close.innerText = 'Close' + _close.addEventListener('click', () => slideDown()) + _close.addEventListener('keydown', () => slideDown()) + // nav + const _navDiv = document.createElement('div') + _navDiv.className = 'nav' + _navDiv.append(_index, _close) + // gallery + const _gallery = document.createElement('div') + _gallery.className = 'gallery' + _gallery.append(_swiperNode) + _gallery.append(_navDiv) + + /** + * curtain + */ + const _curtain = document.createElement('div') + _curtain.className = 'curtain' + + /** + * container + * |- gallery + * |- curtain + */ + container.append(_gallery, _curtain) +} diff --git a/assets/ts/mobile/scroll.ts b/assets/ts/mobile/scroll.ts new file mode 100644 index 0000000..46ecb41 --- /dev/null +++ b/assets/ts/mobile/scroll.ts @@ -0,0 +1,3 @@ +import { Watchable } from '../utils' + +export const scrollable = new Watchable(true) diff --git a/layouts/partials/head.html b/layouts/partials/head.html index c3d84e6..44d92c6 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -1,9 +1,13 @@ {{- $fingerprint := .Scratch.Get "fingerprint" | default "" -}} -{{- $style := dict "Source" "css/style.scss" "Fingerprint" $fingerprint -}} +{{- $style := dict "Source" "scss/style.scss" "Fingerprint" $fingerprint -}} {{- $options := dict "targetPath" "css/style.min.css" "enableSourceMap" true -}} {{- $style = dict "Context" . "ToCSS" $options | merge $style -}} {{- partial "plugin/style.html" $style -}} {{- $esBuildOpts := dict "minify" hugo.IsProduction -}} {{- $script := resources.Get "ts/main.ts" | js.Build $esBuildOpts -}} + From c419b304dfad63e9c6fb69828ecf8dc7455f1fba Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 22:11:32 +0800 Subject: [PATCH 11/13] feat(nav.scss): add styles for navigation bar - Added styles for the navigation bar to improve the appearance and functionality of the navigation component. - The navigation bar now has a fixed position at the bottom of the screen and is displayed as a flex container with space between and aligned center. - The width of the navigation bar is set to 100% and the height is set using a CSS variable (--nav-height). - Added padding to the navigation bar for spacing. - The navigation bar has a white background and a z-index value of (--z-nav) to ensure it appears above other elements. - The pointer-events property is set to "all" to maintain functionality while the container is locked. - Added styles for the ".num" and ".current" classes. - Added media queries to adjust the position and visibility of the navigation bar on smaller screens or devices without hover capability. --- assets/{css => scss}/_partial/_nav.scss | 1 - 1 file changed, 1 deletion(-) rename assets/{css => scss}/_partial/_nav.scss (96%) diff --git a/assets/css/_partial/_nav.scss b/assets/scss/_partial/_nav.scss similarity index 96% rename from assets/css/_partial/_nav.scss rename to assets/scss/_partial/_nav.scss index 6b4d1c3..586b3d9 100644 --- a/assets/css/_partial/_nav.scss +++ b/assets/scss/_partial/_nav.scss @@ -34,7 +34,6 @@ nav { @media (max-width: $tablet), (hover: none) { nav { top: 0; - position: sticky; } .index, From 047ec5c63031d3285245db99c752b6a525670f5c Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 22:12:06 +0800 Subject: [PATCH 12/13] feat(container.scss): add container styles for fixed position and scrolling behavior feat(container.ts): create container module to handle scrollable behavior and add/remove disableScroll class fix(customCursor.ts): update append target for cursor element to use container instead of main fix(stage.ts): update append target for stage element to use container instead of main fix(stageNav.ts): update append target for navOverlay element to use container instead of main feat(main.ts): initialize container module and conditionally initialize stage and stageNav modules based on device type fix(nav.ts): update references to state module functions to use state.get() instead of getState() --- assets/scss/_partial/_container.scss | 19 +++++++++++++++++++ assets/ts/container.ts | 14 ++++++++++++++ assets/ts/desktop/customCursor.ts | 3 ++- assets/ts/desktop/stage.ts | 15 ++++++++------- assets/ts/desktop/stageNav.ts | 9 +++++---- assets/ts/main.ts | 22 +++++++++++++++++----- assets/ts/nav.ts | 8 ++++---- layouts/index.html | 2 +- 8 files changed, 70 insertions(+), 22 deletions(-) create mode 100644 assets/scss/_partial/_container.scss create mode 100644 assets/ts/container.ts diff --git a/assets/scss/_partial/_container.scss b/assets/scss/_partial/_container.scss new file mode 100644 index 0000000..330d239 --- /dev/null +++ b/assets/scss/_partial/_container.scss @@ -0,0 +1,19 @@ +.container { + position: fixed; + top: 0; + z-index: 0; + + width: 100vw; + height: var(--window-height); + + overflow-y: scroll; + overflow-x: hidden; + background: white; + + overscroll-behavior: none; + -webkit-overflow-scrolling: none; +} + +.disableScroll { + pointer-events: none; +} diff --git a/assets/ts/container.ts b/assets/ts/container.ts new file mode 100644 index 0000000..8dd3c99 --- /dev/null +++ b/assets/ts/container.ts @@ -0,0 +1,14 @@ +import { scrollable } from './mobile/scroll' + +export let container: HTMLDivElement + +export function initContainer(): void { + container = document.getElementsByClassName('container').item(0) as HTMLDivElement + scrollable.addWatcher(() => { + if (scrollable.get()) { + container.classList.remove('disableScroll') + } else { + container.classList.add('disableScroll') + } + }) +} diff --git a/assets/ts/desktop/customCursor.ts b/assets/ts/desktop/customCursor.ts index ab67c99..8d91739 100644 --- a/assets/ts/desktop/customCursor.ts +++ b/assets/ts/desktop/customCursor.ts @@ -1,4 +1,5 @@ import { active } from './stage' +import { container } from '../container' /** * variables @@ -32,7 +33,7 @@ export function initCustomCursor(): void { // append cursor inner to cursor cursor.append(cursorInner) // append cursor to main - document.getElementById('main')!.append(cursor) + container.append(cursor) // bind mousemove event to window window.addEventListener('mousemove', onMouse) // add active callback diff --git a/assets/ts/desktop/stage.ts b/assets/ts/desktop/stage.ts index 1598251..0400671 100644 --- a/assets/ts/desktop/stage.ts +++ b/assets/ts/desktop/stage.ts @@ -1,7 +1,8 @@ -import { incIndex, getState } from '../state' +import { incIndex, state } from '../state' import { gsap, Power3 } from 'gsap' import { ImageJSON } from '../resources' import { Watchable } from '../utils' +import { container } from '../container' /** * types @@ -29,7 +30,7 @@ function getElTrail(): HTMLImageElement[] { } function getElTrailCurrent(): HTMLImageElement[] { - return getElTrail().slice(-getState().trailLength) + return getElTrail().slice(-state.get().trailLength) } function getElTrailInactive(): HTMLImageElement[] { @@ -52,12 +53,12 @@ function onMouse(e: MouseEvent): void { const cord = { x: e.clientX, y: e.clientY } const travelDist = Math.hypot(cord.x - last.x, cord.y - last.y) - if (travelDist > getState().threshold) { + if (travelDist > state.get().threshold) { last = cord incIndex() - const newHist = { i: getState().index, ...cord } - cordHist.set([...cordHist.get(), newHist].slice(-getState().length)) + const newHist = { i: state.get().index, ...cord } + cordHist.set([...cordHist.get(), newHist].slice(-state.get().length)) } } @@ -70,7 +71,7 @@ function setPositions(): void { x: (i: number) => cordHist.get()[i].x - window.innerWidth / 2, y: (i: number) => cordHist.get()[i].y - window.innerHeight / 2, opacity: (i: number) => - i + 1 + getState().trailLength <= cordHist.get().length ? 0 : 1, + i + 1 + state.get().trailLength <= cordHist.get().length ? 0 : 1, zIndex: (i: number) => i, scale: 0.6 }) @@ -192,5 +193,5 @@ function createStage(ijs: ImageJSON[]): void { e.alt = 'image' stage.append(e) } - document.getElementById('main')!.append(stage) + container.append(stage) } diff --git a/assets/ts/desktop/stageNav.ts b/assets/ts/desktop/stageNav.ts index 7b60c6a..61e42b7 100644 --- a/assets/ts/desktop/stageNav.ts +++ b/assets/ts/desktop/stageNav.ts @@ -1,7 +1,8 @@ import { setCustomCursor } from './customCursor' -import { decIndex, incIndex, getState } from '../state' +import { decIndex, incIndex, state } from '../state' import { increment, decrement } from '../utils' import { cordHist, isOpen, isAnimating, active, minimizeImage } from './stage' +import { container } from '../container' /** * types @@ -71,7 +72,7 @@ export function initStageNav() { navOverlay.classList.remove('active') } }) - document.getElementById('main')!.append(navOverlay) + container.append(navOverlay) window.addEventListener('keydown', handleKey) } @@ -83,7 +84,7 @@ function nextImage() { if (isAnimating.get()) return cordHist.set( cordHist.get().map((item) => { - return { ...item, i: increment(item.i, getState().length) } + return { ...item, i: increment(item.i, state.get().length) } }) ) @@ -94,7 +95,7 @@ function prevImage() { if (isAnimating.get()) return cordHist.set( cordHist.get().map((item) => { - return { ...item, i: decrement(item.i, getState().length) } + return { ...item, i: decrement(item.i, state.get().length) } }) ) diff --git a/assets/ts/main.ts b/assets/ts/main.ts index 9d209bf..5e82b59 100644 --- a/assets/ts/main.ts +++ b/assets/ts/main.ts @@ -1,13 +1,25 @@ -import { initResources } from './resources' -import { initState } from './state' +import { initContainer } from './container' import { initCustomCursor } from './desktop/customCursor' -import { initNav } from './nav' import { initStage } from './desktop/stage' import { initStageNav } from './desktop/stageNav' +import { initCollection } from './mobile/collection' +import { initGallery } from './mobile/gallery' +import { initNav } from './nav' +import { initResources } from './resources' +import { initState } from './state' +import { isMobile } from './utils' +initContainer() initCustomCursor() const ijs = initResources() initState(ijs.length) -initStage(ijs) -initStageNav() + initNav() + +if (!isMobile()) { + initStage(ijs) + initStageNav() +} else { + initCollection(ijs) + initGallery(ijs) +} diff --git a/assets/ts/nav.ts b/assets/ts/nav.ts index 833aa7e..25282d4 100644 --- a/assets/ts/nav.ts +++ b/assets/ts/nav.ts @@ -1,4 +1,4 @@ -import { getState, incThreshold, decThreshold } from './state' +import { decThreshold, incThreshold, state } from './state' import { expand } from './utils' /** @@ -48,15 +48,15 @@ export function initNav() { // helper export function updateThresholdText(): void { - const thresholdValue: string = expand(getState().threshold) + const thresholdValue: string = expand(state.get().threshold) thresholdDispNums.forEach((e: HTMLSpanElement, i: number) => { e.innerText = thresholdValue[i] }) } export function updateIndexText(): void { - const indexValue: string = expand(getState().index + 1) - const indexLength: string = expand(getState().length) + const indexValue: string = expand(state.get().index + 1) + const indexLength: string = expand(state.get().length) indexDispNums.forEach((e: HTMLSpanElement, i: number) => { if (i < 4) { e.innerText = indexValue[i] diff --git a/layouts/index.html b/layouts/index.html index 9fe8cfc..5e9a693 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -37,6 +37,6 @@ {{ end }} - {{ partial "nav.html" . }} +
{{ partial "nav.html" . }}
From 6e4213054c614bfccc1d048579c1c8b0caea1968 Mon Sep 17 00:00:00 2001 From: Sped0n Date: Sun, 29 Oct 2023 22:12:31 +0800 Subject: [PATCH 13/13] refactor(state.ts): refactor state management to use a Watchable class for improved reactivity and encapsulation fix(state.ts): fix bug in decThreshold function where the wrong value was being passed to updateThreshold function --- assets/ts/state.ts | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/assets/ts/state.ts b/assets/ts/state.ts index 4aebfe9..482f215 100644 --- a/assets/ts/state.ts +++ b/assets/ts/state.ts @@ -1,5 +1,5 @@ -import { increment, decrement } from './utils' import { updateIndexText, updateThresholdText } from './nav' +import { Watchable, decrement, increment } from './utils' const thresholds = [ { threshold: 20, trailLength: 20 }, @@ -18,43 +18,46 @@ const defaultState = { export type State = typeof defaultState -let state = defaultState - -export function getState(): State { - // return a copy of state - return Object.create( - Object.getPrototypeOf(state), - Object.getOwnPropertyDescriptors(state) - ) -} +export const state = new Watchable(defaultState) export function initState(length: number): void { - state.length = length + const s = state.get() + s.length = length + state.set(s) + state.addWatcher(() => { + updateIndexText() + updateThresholdText() + }) } export function setIndex(index: number): void { - state.index = index - updateIndexText() + const s = state.get() + s.index = index + state.set(s) } export function incIndex(): void { - state.index = increment(state.index, state.length) - updateIndexText() + const s = state.get() + s.index = increment(s.index, s.length) + state.set(s) } export function decIndex(): void { - state.index = decrement(state.index, state.length) - updateIndexText() + const s = state.get() + s.index = decrement(s.index, s.length) + state.set(s) } export function incThreshold(): void { - state = updateThreshold(state, 1) - updateThresholdText() + let s = state.get() + s = updateThreshold(s, 1) + state.set(s) } export function decThreshold(): void { - state = updateThreshold(state, -1) - updateThresholdText() + let s = state.get() + s = updateThreshold(s, 1) + state.set(s) } // helper