diff --git a/duomo.scss b/index.scss similarity index 100% rename from duomo.scss rename to index.scss diff --git a/package.json b/package.json index 8ee15ba..bb66252 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "@zaydek/duomo", "version": "0.7.6", - "main": "dist/prod.css", + "main": "dist/prod-full.css", "license": "MIT", "files": [ "dist/", "src/sass/**/*.{css,scss}", - "duomo.scss" + "index.scss" ], "scripts": { "watch": "nodemon --exec 'sass --style=compressed src/consumer.scss dist/dev.css && yarn prettier --write dist/dev.css' --ext css,scss --watch src", @@ -15,9 +15,8 @@ "build-css-dev-full": "sass --style=compressed scripts/dev-full.scss dist/dev-full.css && yarn prettier --write dist/dev-full.css", "build-css-prod": "sass --style=compressed scripts/prod.scss dist/prod.css", "build-css-prod-full": "sass --style=compressed scripts/prod-full.scss dist/prod-full.css", - "build-js": "tsc", - "build-browser-js": "node scripts/browser.js", - "build": "rm -rf dist && yarn concurrently --raw 'yarn build-css-dev' 'yarn build-css-dev-full' 'yarn build-css-prod' 'yarn build-css-prod-full' 'yarn build-js' 'yarn build-browser-js'", + "build-js": "tsc && node scripts/browser.js", + "build": "rm -rf dist && yarn concurrently --raw 'yarn build-css-dev' 'yarn build-css-dev-full' 'yarn build-css-prod' 'yarn build-css-prod-full' 'yarn build-js'", "publish-dist-dry-run": "yarn build && npm publish --dry-run" }, "devDependencies": { diff --git a/src/runtime/runtime.ts b/src/runtime/runtime.ts index 653eb02..fc5fc8f 100644 --- a/src/runtime/runtime.ts +++ b/src/runtime/runtime.ts @@ -1,18 +1,33 @@ -const THEME_PREFERENCE_KEY = "duomo-theme-preference" as const +/* + * TypeScript + */ -type DevMode = "development" | "production" +type DEV_MODE = "development" | "production" + +declare global { + interface Window { + Duomo: IRuntime + } +} + +/* + * Runtime + */ + +const themePreferenceKey = "duomo-theme-preference" as const interface IRuntime { - init(mode: DevMode): () => void + init(mode: DEV_MODE): () => void toggleDebugMode(): void + toggleDebugSpaceMode(): void toggleDarkMode(): void } // prettier-ignore -function localStoragePrefersDarkMode() { +function LSPrefersDarkMode() { const ok = ( - THEME_PREFERENCE_KEY in window.localStorage && - window.localStorage[THEME_PREFERENCE_KEY] === "dark" + themePreferenceKey in window.localStorage && + window.localStorage[themePreferenceKey] === "dark" ) return ok } @@ -27,15 +42,16 @@ function OSPrefersDarkMode() { } const Duomo: IRuntime = { - init(mode: DevMode = "production") { - const deferers: Array<() => void> = [] + init(mode: DEV_MODE = "production") { + const html = document.documentElement + const deferers: (() => void)[] = [] console.log("[Duomo] init=true") // NOTE: localStorage takes precedence. // TODO: Change to `[data-theme="dark"]`? - if (localStoragePrefersDarkMode() || !OSPrefersDarkMode()) { - document.body.classList.add("dark") + if (LSPrefersDarkMode() || !OSPrefersDarkMode()) { + html.setAttribute("data-theme", "dark") } if ("matchMedia" in window) { @@ -49,21 +65,32 @@ const Duomo: IRuntime = { } if (mode !== "production") { - const handleKeyDownDarkMode = (e: KeyboardEvent) => { - if (e.ctrlKey && (e.key.toLowerCase() === "d" || e.keyCode === 68)) { - Duomo.toggleDarkMode() - } - } - document.addEventListener("keydown", handleKeyDownDarkMode) - deferers.push(() => document.removeEventListener("keydown", handleKeyDownDarkMode)) - + // Key: `d`. const handleKeyDownDebugMode = (e: KeyboardEvent) => { - if (!e.ctrlKey && (e.key.toLowerCase() === "d" || e.keyCode === 68)) { + if (!e.ctrlKey && !e.altKey && (e.key.toLowerCase() === "d" || e.keyCode === 68)) { Duomo.toggleDebugMode() } } document.addEventListener("keydown", handleKeyDownDebugMode) deferers.push(() => document.removeEventListener("keydown", handleKeyDownDebugMode)) + + // Key: `alt-d`. + const handleKeyDownDebugSpaceMode = (e: KeyboardEvent) => { + if (!e.ctrlKey && e.altKey && (e.key.toLowerCase() === "d" || e.keyCode === 68)) { + Duomo.toggleDebugSpaceMode() + } + } + document.addEventListener("keydown", handleKeyDownDebugSpaceMode) + deferers.push(() => document.removeEventListener("keydown", handleKeyDownDebugSpaceMode)) + + // Key: `ctrl-d`. + const handleKeyDownDarkMode = (e: KeyboardEvent) => { + if (e.ctrlKey && !e.altKey && (e.key.toLowerCase() === "d" || e.keyCode === 68)) { + Duomo.toggleDarkMode() + } + } + document.addEventListener("keydown", handleKeyDownDarkMode) + deferers.push(() => document.removeEventListener("keydown", handleKeyDownDarkMode)) } return () => { @@ -72,43 +99,53 @@ const Duomo: IRuntime = { } }, toggleDebugMode() { - const hasAttribute = document.body.hasAttribute("data-debug") + const html = document.documentElement + + const hasAttribute = html.hasAttribute("data-debug") if (!hasAttribute) { console.log("[Duomo] debugMode=on") - document.body.setAttribute("data-debug", "true") + html.setAttribute("data-debug", "true") } else { console.log("[Duomo] debugMode=off") - document.body.removeAttribute("data-debug") + html.removeAttribute("data-debug") + } + }, + toggleDebugSpaceMode() { + const html = document.documentElement + + const hasAttribute = html.hasAttribute("data-debug-space") + if (!hasAttribute) { + console.log("[Duomo] debugSpaceMode=on") + html.setAttribute("data-debug-space", "true") + } else { + console.log("[Duomo] debugSpaceMode=off") + html.removeAttribute("data-debug-space") } }, // TODO: `toggleDarkMode` is not currently cancelable. Should it be? // TODO: Implement `toggleMode(mode: string = "dark")`. toggleDarkMode() { - document.body.setAttribute("data-theme-effect", "true") + const html = document.documentElement + + html.setAttribute("data-theme-effect", "true") setTimeout(() => { - const hasAttribute = document.body.hasAttribute("data-theme") + const hasAttribute = html.hasAttribute("data-theme") if (!hasAttribute) { console.log("[Duomo] darkMode=on") - document.body.setAttribute("data-theme", "dark") - window.localStorage.setItem(THEME_PREFERENCE_KEY, "dark") + html.setAttribute("data-theme", "dark") + window.localStorage.setItem(themePreferenceKey, "dark") } else { console.log("[Duomo] darkMode=off") - document.body.removeAttribute("data-theme") - window.localStorage.setItem(THEME_PREFERENCE_KEY, "light") + html.removeAttribute("data-theme") + window.localStorage.setItem(themePreferenceKey, "light") } setTimeout(() => { - document.body.removeAttribute("data-theme-effect") + html.removeAttribute("data-theme-effect") }, 300) }, 25) }, } -declare global { - interface Window { - Duomo: IRuntime - } -} - ;(() => { if (typeof window !== "undefined") { window.Duomo = Duomo diff --git a/src/sass/extensions/stacks.scss b/src/sass/extensions/stacks.scss index a0d86b4..a682cdd 100644 --- a/src/sass/extensions/stacks.scss +++ b/src/sass/extensions/stacks.scss @@ -172,17 +172,13 @@ $-align-opts: ( */ #{variant(w-auto, $v)} { + --dm-align-self: stretch; width: auto; } - @each $rv in range() { - #{variant(w-#{$rv}, $v)} { - --dm-align-self: center; - width: rem($rv); - } - } - @each $rv in (100%, 100vw) { + @each $rv in to-array(range(), 100%, 100vw) { #{variant(w-#{desc($rv)}, $v)} { - width: $rv; + --dm-align-self: center; + width: resolve($rv, rem); } } @@ -193,19 +189,26 @@ $-align-opts: ( */ #{variant(h-auto, $v)} { + --dm-align-self: stretch; height: auto; } - @each $rv in range() { - #{variant(h-#{$rv}, $v)} { - --dm-align-self: center; - height: rem($rv); - } - } - @each $rv in (100%, 100vh) { + @each $rv in to-array(range(), 100%, 100vh) { #{variant(h-#{desc($rv)}, $v)} { - height: $rv; + --dm-align-self: center; + height: resolve($rv, rem); } } + // @each $rv in range() { + // #{variant(h-#{$rv}, $v)} { + // --dm-align-self: center; + // height: rem($rv); + // } + // } + // @each $rv in (100%, 100vh) { + // #{variant(h-#{desc($rv)}, $v)} { + // height: $rv; + // } + // } /* * <... align-self-*> diff --git a/src/sass/headers/data-stagger.scss b/src/sass/headers/data-stagger.scss index 66d8862..11d3319 100644 --- a/src/sass/headers/data-stagger.scss +++ b/src/sass/headers/data-stagger.scss @@ -1,17 +1,17 @@ @mixin data-stagger { - [data-stagger-1] { + [data-stagger="1"] { width: var(--stagger-1-width); } - [data-stagger-2] { + [data-stagger="2"] { width: var(--stagger-2-width); } - [data-stagger-3] { + [data-stagger="3"] { width: var(--stagger-3-width); } - [data-stagger-4] { + [data-stagger="4"] { width: var(--stagger-4-width); } - [data-stagger-last] { + [data-stagger="last"] { width: var(--stagger-last-width); } } diff --git a/src/sass/headers/introspection.scss b/src/sass/headers/introspection.scss index dff4b60..ee58b87 100644 --- a/src/sass/headers/introspection.scss +++ b/src/sass/headers/introspection.scss @@ -19,25 +19,25 @@ --ui-mono: #{font(mono, $raw: true)}; // CSS reset vars. - --placeholder-color-default: #{color(gray-400)}; - --border-color-default: #{color(gray-200)}; + --placeholder-color-default: hsl(#{color(gray-400)}); + --border-color-default: hsl(#{color(gray-300)}); --transition-duration-default: 300ms; --transition-timing-function-default: #{timing(ease-out)}; - // `data-stagger` presets. + // [data-stagger] --stagger-1-width: #{math.percentage(4 / 8)}; --stagger-2-width: #{math.percentage(6 / 8)}; --stagger-3-width: #{math.percentage(7 / 8)}; --stagger-4-width: #{math.percentage(5 / 8)}; --stagger-last-width: 50%; - // `data-debug` presets. - --debug-outline: 2px solid hsla(210, 100%, 50%, 0.5); + // [data-debug] + --debug-outline: 2px solid hsla(210, 100%, 50%, 0.25); --debug-empty-spacer-outline: 1px dashed hsla(210, 100%, 50%, 0.25); --debug-outline-offset: -2px; --debug-spacer-background-color: hsla(210, 100%, 50%, 0.25); - // `data-debug-space` presets. + // [data-debug-space] --debug-space-background-color: hsla(210, 100%, 50%, 0.1); } } diff --git a/src/sass/helpers/getters.scss b/src/sass/helpers/getters.scss index e77575a..a830d67 100644 --- a/src/sass/helpers/getters.scss +++ b/src/sass/helpers/getters.scss @@ -1,10 +1,11 @@ @use "sass:map"; @use "sass:meta"; -@use "../configuration"; @use "escapers" as *; @use "resolvers" as *; +@use "../configuration"; + // Ex: // // n(-1) -> "-"