diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..ab28f3e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "tabWidth": 4 +} \ No newline at end of file diff --git a/README.md b/README.md index d901a23..adb6c26 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,11 @@ it will be styled to indicate that. Animal Sciences Major - Companion Animal Equine Science - Food Animal Production and Management - Science, Pre-Veterinary, and Medical + Pre-Veterinary and Medical + Food Animal + Companion Animal Equine - Computer Science & Animal Science + Computer & Animal Science Some Third Thing diff --git a/package-lock.json b/package-lock.json index b7d1c0b..fe0681b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,9 @@ "lit": "3.1.3" }, "devDependencies": { + "postcss-nested": "^6.2.0", + "prettier": "^3.3.3", + "rollup-plugin-postcss-lit": "^2.1.0", "vite": "^5.2.0" } }, @@ -396,6 +399,28 @@ "@lit-labs/ssr-dom-shim": "^1.2.0" } }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", + "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.21.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz", @@ -615,6 +640,77 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -653,6 +749,21 @@ "@esbuild/win32-x64": "0.21.5" } }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -667,6 +778,41 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, "node_modules/lit": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.3.tgz", @@ -695,6 +841,83 @@ "@types/trusted-types": "^2.0.2" } }, + "node_modules/magic-string": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.23.2.tgz", + "integrity": "sha512-oIUZaAxbcxYIp4AyLafV6OVKoB3YouZs0UTCJ8mOKBHNyJgGDaMJ4TgA+VylJh6fx7EQCC52XkbURxxG9IoJXA==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.1" + } + }, + "node_modules/merge-source-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", + "integrity": "sha512-PGSmS0kfnTnMJCzJ16BLLCEe6oeYCamKFFdQKshi4BmM6FUwipjVOcBFGxqtQtirtAG4iZvHlqST9CpZKqlRjA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/mutexify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mutexify/-/mutexify-1.4.0.tgz", + "integrity": "sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg==", + "dev": true, + "dependencies": { + "queue-tick": "^1.0.0" + } + }, + "node_modules/nanobench": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nanobench/-/nanobench-2.1.1.tgz", + "integrity": "sha512-z+Vv7zElcjN+OpzAxAquUayFLGK3JI/ubCl0Oh64YQqsTGG09CGqieJVQw4ui8huDnnAgrvTv93qi5UaOoNj8A==", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^0.1.2", + "chalk": "^1.1.3", + "mutexify": "^1.1.0", + "pretty-hrtime": "^1.0.2" + }, + "bin": { + "nanobench": "run.js", + "nanobench-compare": "compare.js" + } + }, + "node_modules/nanobench/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanobench/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanobench/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -719,6 +942,18 @@ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/postcss": { "version": "8.4.41", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", @@ -747,6 +982,74 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true + }, "node_modules/rollup": { "version": "4.21.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz", @@ -782,6 +1085,25 @@ "fsevents": "~2.3.2" } }, + "node_modules/rollup-plugin-postcss-lit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-postcss-lit/-/rollup-plugin-postcss-lit-2.1.0.tgz", + "integrity": "sha512-rtgCG0U2GkT5aLymkZEKXLq36sgtWVJFtL97Vmek0jgaYa6FDs0Xhqd9cCHdDBXPeTctlSZGGs+tpUtIpHMFMQ==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.2", + "transform-ast": "^2.4.4" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", @@ -791,6 +1113,46 @@ "node": ">=0.10.0" } }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/transform-ast": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/transform-ast/-/transform-ast-2.4.4.tgz", + "integrity": "sha512-AxjeZAcIOUO2lev2GDe3/xZ1Q0cVGjIMk5IsriTy8zbWlsEnjeB025AhkhBJHoy997mXpLd4R+kRbvnnQVuQHQ==", + "dev": true, + "dependencies": { + "acorn-node": "^1.3.0", + "convert-source-map": "^1.5.1", + "dash-ast": "^1.0.0", + "is-buffer": "^2.0.0", + "magic-string": "^0.23.2", + "merge-source-map": "1.0.4", + "nanobench": "^2.1.1" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/vite": { "version": "5.4.2", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", @@ -849,6 +1211,15 @@ "optional": true } } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } } } } diff --git a/package.json b/package.json index 78c7288..9bb591b 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "default": "./dist/ilw-section-nav.js" } }, - "main":"./dist/ilw-section-nav.js", + "main": "./dist/ilw-section-nav.js", "scripts": { "dev": "vite", "build": "vite build --config vite.build.config.js --emptyOutDir", @@ -29,6 +29,8 @@ "lit": "3.1.3" }, "devDependencies": { - "vite": "^5.2.0" + "vite": "^5.2.0", + "prettier": "^3.3.3", + "postcss-nested": "^6.2.0" } } \ No newline at end of file diff --git a/parse-vars.js b/parse-vars.js new file mode 100644 index 0000000..f1f617f --- /dev/null +++ b/parse-vars.js @@ -0,0 +1,16 @@ +import {readFileSync} from "fs"; + +const contents = readFileSync("src/ilw-section-nav.css", "utf-8"); +const regex = /^\s*(--[\w-]+):[^;]+;\s*\/\*\s*(var|vardep):\s*(.+)\*\s*\/$/gm; + +let output = []; +let m; +while (m = regex.exec(contents)) { + output.push({ + name: m[1], + depreciated: m[2] === "vardep", + description: m[3] + }) +} + +console.log(JSON.stringify(output, null, 4)); diff --git a/samples/index.html b/samples/index.html index f21b98c..b3fae59 100644 --- a/samples/index.html +++ b/samples/index.html @@ -1,17 +1,180 @@ - - - + + - - - Section Nav Component + + + + + + + + + + + + + + + + + + + + + + + + + + + Section Nav Component + + + + Toolkit Builder 3 + Whispering Pines College + + + + - - + + +
+

+ Home Academics Graduate programs + +

+ + +

Graduate Programs

+
+ +

Graduate Programs include:

+
    +
  • Environmental Philosophy and Ethics
  • +
  • Forest Ecology and Conservation
  • +
  • Creative Writing with a focus on Nature Literature
  • +
  • Sustainable Architecture and Design
  • +
  • Mythology and Folklore Studies
  • +
  • Psychology of Mindfulness and Well-being
  • +
  • Renewable Energy Systems and Policy
  • +
  • Herbal Medicine and Botanical Studies
  • +
  • Wildlife Management and Conservation Biology
  • +
  • Cultural Anthropology with a focus on Indigenous Practices
  • +
+
+ +

Each program at Whispering Pines is designed to integrate academic excellence with an appreciation + for the natural world, fostering a unique learning environment for students.

+
+ +

Frequently Asked Questions

+
+
+
+ + Toolkit Builder 3 + Whispering Pines College +
+
1313 Pine Avenue
+
Normal, ZZ 99999
+
Phone: 555-874-3000
+
Email: contact@iou.edu
+
+
+ Give + Apply +
+ + + +

Explore

+ +
+ +

Connect

+ +
+
+
+
- - + \ No newline at end of file diff --git a/src/ManualSlotController.js b/src/ManualSlotController.js new file mode 100644 index 0000000..c6ee0a0 --- /dev/null +++ b/src/ManualSlotController.js @@ -0,0 +1,72 @@ +/** + * A simple Lit reactive controller to apply manual slotting to a component. + * + * Using manual slotting gives us the ability to surround the child nodes with additional + * elements without resorting to manipulating the page's DOM. This is important for + * elements with strict parent-child relationships, like `ul` and `li`, since otherwise + * they would require the component's user to add those elements. + * + * When using this: + * - Make sure your component has `slotAssignment: "manual"` in its shadowRootOptions. + * - Add the `_observer = new ManualSlotController(this)` property to your component's class. + * - In your component's render, map over children to create the slots. Something like: + * + * ``` + * ${map(Array.from(this.children), () => html`
  • `)} + * ``` + */ +export class ManualSlotController { + /** + * @type import("lit").LitElement + * @private + */ + _host; + + /** + * @type MutationObserver + * @private + */ + _observer; + + /** + * @param {import("lit").LitElement} host + */ + constructor(host) { + this._host = host; + this._observer = new MutationObserver((list) => { + this._host.requestUpdate(); + }); + // This binds the controller to the element's lifecycle + host.addController(this); + } + + /** + * Find the child nodes and slots, and assign the children to each slot. + * + * The render of the host component is expected to create the slots, but this + * function will take care of assigning the elements to them. + * @private + */ + _refreshInternal() { + let items = Array.from(this._host.children); + let slots = Array.from(this._host.shadowRoot.querySelectorAll('slot')); + for (let slot of slots) { + if (items.length > 0) { + slot.assign(items.shift()); + } + } + } + + hostUpdated() { + // Called by Lit after the host component's render. + this._refreshInternal(); + } + + hostConnected() { + this._observer.observe(this._host, {childList: true}); + } + + disconnect() { + this._observer.disconnect(); + } +} \ No newline at end of file diff --git a/src/ilw-section-nav.css b/src/ilw-section-nav.css index e69de29..c72992d 100644 --- a/src/ilw-section-nav.css +++ b/src/ilw-section-nav.css @@ -0,0 +1,44 @@ +@layer base { + :root { + --ilw-section-nav--margin: 1.5em 0 0 0; + + --ilw-section-nav--color: var(--il-blue); + --ilw-section-nav--color--focus: var(--il-blue); + --ilw-section-nav--color--hover: var(--il-altgeld); + --ilw-section-nav--color--active: var(--il-altgeld); + --ilw-section-nav--line-height: 2.75rem; /*var: Height of a nav element*/ + --ilw-section-nav--level-padding: 0.9375rem; /*var: Left indentation for levels*/ + --ilw-section-nav--level2-padding: 1.5625rem; /*var: Specific indentation for level 2 children*/ + --ilw-section-nav--level0-font-size: 1.125rem; /*var: First level children font size*/ + --ilw-section-nav--level1-font-size: 1rem; /*var: Font size for all deeper children*/ + --ilw-section-nav--font-weight: 600; /*var: Font weight for menu items*/ + + --ilw-section-nav--item-padding: 0 10px 0 20px; + + --ilw-section-nav--level1-border: 1px solid var(--il-storm-lighter-3); + + --ilw-section-nav--root-font-size: 1.25rem; + --ilw-section-nav--root-background: var(--il-storm-lighter-4); + --ilw-section-nav--root-font-weight: 700; + } +} + +ilw-section-nav { + a { + color: var(--ilw-section-nav--color); + text-decoration: var(--ilw-link--focused-background-color); + display: block; + padding: var(--ilw-section-nav--item-padding); + + &[aria-current="page"] { + color: var(--ilw-section-nav--color--active); + } + &:hover { + text-decoration: underline; + color: var(--ilw-section-nav--color--hover); + } + &:focus { + color: var(--ilw-section-nav--color--focus); + } + } +} diff --git a/src/ilw-section-nav.js b/src/ilw-section-nav.js index ae6ef62..668a21e 100644 --- a/src/ilw-section-nav.js +++ b/src/ilw-section-nav.js @@ -1,12 +1,25 @@ -import { LitElement, html } from 'lit'; -import styles from './ilw-section-nav.styles'; -import './ilw-section-nav.css'; +import { LitElement, html } from "lit"; +import styles from "./ilw-section-nav.styles"; +import "./ilw-section-nav.css"; +import { ManualSlotController } from "./ManualSlotController.js"; +import { map } from "lit/directives/map.js"; +import { classMap } from "lit/directives/class-map.js"; class SectionNav extends LitElement { + static shadowRootOptions = { + ...LitElement.shadowRootOptions, + slotAssignment: "manual", + }; static get properties() { return { - theme: { type: String, attribute: true } + theme: {}, + collapse: { type: Boolean }, + open: { reflect: true }, + label: {}, + noRoot: { type: Boolean, attribute: "no-root" }, + _isRoot: { state: true, type: Boolean }, + _level: {state: true, type: Number} }; } @@ -14,18 +27,78 @@ class SectionNav extends LitElement { return styles; } + _observer = new ManualSlotController(this); + constructor() { super(); - this.theme = ''; + this.theme = ""; + this.collapse = false; + this.open = "false"; + this.label = "Pages In This Section"; + this.noRoot = false; + this._isRoot = true; + this._level = 0; + } + + connectedCallback() { + super.connectedCallback() + let parent = this.parentElement.closest("ilw-section-nav"); + if (!parent) { + this._isRoot = true; + } else { + this._isRoot = false; + this._level = parent._level + 1; + } + } + + /** + * Toggle between open and closed states when collapsed. + * + * @arg {"true" | "false" | undefined} open Provide the argument to force a specific state. + */ + toggle(open = this.open) { + if (open) { + if ( this.open === open) { + return; + } + this.open = open; + } else if (this.open === "true") { + this.open = "false"; + } else { + this.open = "true"; + } + } render() { - return html` -
    - -
    - `; + const ul = html` + + `; + if (this._isRoot) { + const classes = { + "section-nav-top": true, + "force-collapse": this.collapse, + "style-root": !this.noRoot, + "open": this.open === "true" + } + return html` +
    + +
    ` + } + return ul; } } -customElements.define('ilw-section-nav', SectionNav); \ No newline at end of file +customElements.define("ilw-section-nav", SectionNav); diff --git a/src/ilw-section-nav.styles.js b/src/ilw-section-nav.styles.js index 9b256ee..33a67f4 100644 --- a/src/ilw-section-nav.styles.js +++ b/src/ilw-section-nav.styles.js @@ -1,5 +1,49 @@ import { css } from 'lit'; export default css` + :host { + display: block; + } + .section-nav-top { + margin: var(--ilw-section-nav--margin); + } + + .section-nav-list { + list-style: none; + padding: 0 0 0 var(--ilw-section-nav--level-padding); + margin: 0; + line-height: var(--ilw-section-nav--line-height); + font-weight: var(--ilw-section-nav--font-weight); + } + + .section-nav-list--level-0 { + padding-left: 0; + font-size: var(--ilw-section-nav--level0-font-size); + } + + .section-nav-list--level-0 > li ::slotted(a) { + border-top: var(--ilw-section-nav--level1-border); + } + + .section-nav-list--level-1 { + font-size: var(--ilw-section-nav--level1-font-size); + } + + .section-nav-list--level-2 { + padding-left: calc(var(--ilw-section-nav--level2-padding)); + } + + .style-root { + ::slotted(a:first-of-type) { + font-size: var(--ilw-section-nav--root-font-size); + background: var(--ilw-section-nav--root-background); + font-weight: var(--ilw-section-nav--root-font-weight); + border-top: none; + } + } + + #section-nav-toggle { + display: none; + } `; \ No newline at end of file diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..641e186 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,13 @@ +import { defineConfig } from "vite"; +import nested from "postcss-nested"; + +export default defineConfig({ + css: { + postcss: { + plugins: [ + // Native nested CSS is buggy in Firefox, so use this in development as well as in builds + nested() + ] + } + }, +});