diff --git a/.github/scripts/publish-jsr.sh b/.github/scripts/publish-jsr.sh new file mode 100755 index 0000000..284917d --- /dev/null +++ b/.github/scripts/publish-jsr.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Publish @kolektiv/themes to JSR via GitHub Actions OIDC (trusted publishing). +# Link the package to this repo on jsr.io — no JSR_TOKEN required in CI. +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "${ROOT}/packages/themes" + +if [ ! -f jsr.json ]; then + echo "::error::packages/themes/jsr.json missing" + exit 1 +fi + +# Sync version from package.json +node -e 'const fs=require("fs");const p=JSON.parse(fs.readFileSync("package.json","utf8"));const j=JSON.parse(fs.readFileSync("jsr.json","utf8"));j.version=p.version;fs.writeFileSync("jsr.json",JSON.stringify(j,null,2)+"\n");' + +if [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then + echo "::warning::Not running under Actions OIDC; skipping JSR publish (link package on jsr.io for trusted publishing)" + exit 0 +fi + +echo "publishing to JSR via OIDC (npx jsr publish)" +npx --yes jsr publish --allow-slow-types diff --git a/.github/scripts/publish-maven.sh b/.github/scripts/publish-maven.sh new file mode 100755 index 0000000..316f730 --- /dev/null +++ b/.github/scripts/publish-maven.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Publish themes Maven artifacts to GitHub Packages (when token present) and Yuri Capital. +set -uo pipefail + +VERSION="$(grep -E '^[[:space:]]*version[[:space:]]*=' build.gradle.kts | head -n1 | sed -E 's/.*version[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/' | tr -d '[:space:]')" +if [ -z "${VERSION}" ]; then + # allprojects version in root build.gradle.kts + VERSION="$(rg -oN 'version = "([^"]+)"' build.gradle.kts | head -1 | sed -E 's/version = "([^"]+)"/\1/')" +fi +if [ -z "${VERSION}" ]; then + echo "::error::could not read version from build.gradle.kts" + exit 1 +fi + +echo "publishing dev.kolektiv.themes:themes:${VERSION}" + +GRADLE_ARGS=(:themes:publish --continue) +export GRADLE_ARGS + +LOG="$(mktemp)" +trap 'rm -f "${LOG}"' EXIT + +./gradlew "${GRADLE_ARGS[@]}" 2>&1 | tee "${LOG}" +status="${PIPESTATUS[0]}" + +if [ "${status}" -eq 0 ]; then + echo "Maven publish succeeded" + exit 0 +fi + +# Tolerate 409 conflicts (already published) +if grep -qE "Received status code 409" "${LOG}"; then + echo "::warning::Maven publish hit 409 conflict(s); treating as already published" + exit 0 +fi + +echo "::error::Maven publish failed" +exit 1 diff --git a/.github/scripts/publish-npm.sh b/.github/scripts/publish-npm.sh old mode 100644 new mode 100755 index a02ddb9..614ee56 --- a/.github/scripts/publish-npm.sh +++ b/.github/scripts/publish-npm.sh @@ -1,42 +1,57 @@ #!/usr/bin/env bash -# Publish @kolektiv/themes to the hosted Nexus repo (brand-npm). -# The repo `.npmrc` maps `@kolektiv` to the `npm-public` group for fetching, so -# we temporarily append the hosted `brand-npm` mapping (with auth). +# Dual-publish @kolektiv/themes to Yuri Capital brand-npm and GitHub Packages (when token present). set -euo pipefail -: "${YURI_CAPITAL_REPO_USERNAME:?set YURI_CAPITAL_REPO_USERNAME}" -: "${YURI_CAPITAL_REPO_PASSWORD:?set YURI_CAPITAL_REPO_PASSWORD}" - -HOST="repo.yuri.capital" -REGISTRY="https://${HOST}/repository/brand-npm/" +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +VERSION="$(node -p "require('${ROOT}/packages/themes/package.json').version")" PACKAGES=(@kolektiv/themes) -VERSION="$(node -p "require('./packages/themes/package.json').version")" - -root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -NPMRC="${root}/.npmrc" -backup="$(mktemp)" -cp "${NPMRC}" "${backup}" -trap 'cp "${backup}" "${NPMRC}"; rm -f "${backup}"' EXIT - -AUTH="$(printf '%s:%s' "${YURI_CAPITAL_REPO_USERNAME}" "${YURI_CAPITAL_REPO_PASSWORD}" | openssl base64 -A)" -path="${REGISTRY#https://}" -path="${path#http://}" - -{ - printf '\n@kolektiv:registry=%s\n' "${REGISTRY}" - printf '//%s:_auth=%s\n' "${path}" "${AUTH}" - printf '//%s:always-auth=true\n' "${path}" -} >>"${NPMRC}" - -already_published() { - npm view "$1@${VERSION}" --registry "${REGISTRY}" >/dev/null 2>&1 + +publish_one_registry() { + local name="$1" + local registry="$2" + local auth_userconfig_lines="$3" + + local NPMRC_PATH="${ROOT}/.npmrc" + local backup + backup="$(mktemp)" + cp "${NPMRC_PATH}" "${backup}" + restore() { cp "${backup}" "${NPMRC_PATH}"; rm -f "${backup}"; } + trap restore EXIT + + { + printf '\n' + printf '%s\n' "${auth_userconfig_lines}" + } >>"${NPMRC_PATH}" + + already_published() { + npm view "$1@${VERSION}" --registry "${registry}" >/dev/null 2>&1 + } + + echo "publishing @kolektiv/themes@${VERSION} to ${name} (${registry})" + for pkg in "${PACKAGES[@]}"; do + if already_published "${pkg}"; then + echo "already published ${pkg}@${VERSION} on ${name}, skipping" + continue + fi + pnpm --filter "${pkg}" publish --no-git-checks --access public --registry "${registry}" + done + + restore + trap - EXIT } -echo "publishing @kolektiv/themes@${VERSION} to ${REGISTRY}" -for pkg in "${PACKAGES[@]}"; do - if already_published "${pkg}"; then - echo "already published ${pkg}@${VERSION}, skipping" - continue - fi - pnpm --filter "${pkg}" publish --no-git-checks --access public --registry "${REGISTRY}" -done +: "${YURI_CAPITAL_REPO_USERNAME:?set YURI_CAPITAL_REPO_USERNAME}" +: "${YURI_CAPITAL_REPO_PASSWORD:?set YURI_CAPITAL_REPO_PASSWORD}" +YURI_REGISTRY="https://repo.yuri.capital/repository/brand-npm/" +YURI_AUTH="$(printf '%s:%s' "${YURI_CAPITAL_REPO_USERNAME}" "${YURI_CAPITAL_REPO_PASSWORD}" | openssl base64 -A)" +YURI_PATH="${YURI_REGISTRY#https://}" +YURI_PATH="${YURI_PATH#http://}" +publish_one_registry "yuri-capital" "${YURI_REGISTRY}" "$(printf '@kolektiv:registry=%s\n//%s:_auth=%s\n//%s:always-auth=true' "${YURI_REGISTRY}" "${YURI_PATH}" "${YURI_AUTH}" "${YURI_PATH}")" + +if [ -n "${GITHUB_TOKEN:-}" ] || [ -n "${NODE_AUTH_TOKEN:-}" ]; then + TOKEN="${NODE_AUTH_TOKEN:-${GITHUB_TOKEN}}" + GH_REGISTRY="https://npm.pkg.github.com/" + publish_one_registry "github-packages" "${GH_REGISTRY}" "$(printf '@kolektiv:registry=%s\n//npm.pkg.github.com/:_authToken=%s\n//npm.pkg.github.com/:always-auth=true' "${GH_REGISTRY}" "${TOKEN}")" +else + echo "::warning::GITHUB_TOKEN/NODE_AUTH_TOKEN unset; skipping npm GitHub Packages publish" +fi diff --git a/.gitignore b/.gitignore index dd6e803..e94b8e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,13 @@ -node_modules/ -dist/ +*.iml *.log +*.tgz .DS_Store +.gradle/ +.idea/ +.kotlin/ +build/ +dist/ +kotlin-js-store/ +local.properties +node_modules/ +out/ diff --git a/CHANGELOG.md b/CHANGELOG.md index c01c490..95a7c22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.0.1-SNAPSHOT.3] - 2026-09-15 + +### Added + +- Compose Multiplatform module (`dev.kolektiv.themes:themes`) with `DaisyColors`, + `KolektivTheme`, and the seven palettes generated from `tokens.json`. +- Gradle wrapper so Kalendee / Blawk can `includeBuild` this repo. + ## [0.0.1-SNAPSHOT.2] - 2026-09-13 ### Changed diff --git a/README.md b/README.md index 3ddf73e..787d5ff 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,21 @@ targets from one source: | `@kolektiv/themes/theme.css` | daisyUI-compatible `[data-theme]` colour variables | | `@kolektiv/themes/shiki` | Shiki theme registrations (Kolektiv light/dark) | | `@kolektiv/themes/tokens.json` | raw tokens for Compose / other platforms | +| `dev.kolektiv.themes:themes` | Compose Multiplatform `DaisyColors` + `KolektivTheme` | **Colour-only by design.** A theme declares `color-scheme` and the twenty daisyUI colour variables; each app owns its radii, sizes, borders and density. Palettes: `nord`, `catppuccin-latte/frappe/macchiato/mocha` (extracted from Keel), and -`kolektivcomputer-lig/dark`. Each also maps to a Shiki analog via `shikiThemeFor` +`kolektiv-light` / `kolektiv-dark` (CSS aliases `kolektivcomputer-lig` / `kolektivcomputer-dark`). Each also maps to a Shiki analog via `shikiThemeFor` (`light`/`dark` → GitHub light/dark, `nord` → `nord`, catppuccin → catppuccin, kolektiv → kolektiv). +## Publishing + +See [docs/PUBLISHING.md](./docs/PUBLISHING.md). Maven coordinates: `dev.kolektiv.themes:themes` (Yuri Capital + GitHub Packages). npm: `` `@kolektiv/themes` `` (Yuri `brand-npm` + GitHub Packages). JSR: `` `@kolektiv/themes` `` when linked. + +Until the first Maven publish lands, Compose consumers can still use `includeBuild` + ## Using it ```bash @@ -39,12 +46,49 @@ import { kolektivDark } from '@kolektiv/themes/shiki'; Set `` (etc.) and every daisyUI component follows. + +## Compose + +Colour-only palettes as `dev.kolektiv.themes:themes` (version `0.0.1-SNAPSHOT.3`): + +```kotlin +implementation("dev.kolektiv.themes:themes:0.0.1-SNAPSHOT.3") + +KolektivTheme(KolektivThemes.kolektivDark) { + val colors = KolektivTheme.colors +} +``` + +Until Maven is published to `repo.yuri.capital`, consume via `includeBuild`: + +```kotlin +// settings.gradle.kts +includeBuild("../themes") { + dependencySubstitution { + substitute(module("dev.kolektiv.themes:themes")) + .using(project(":themes")) + } +} +``` + +Radii and density stay in the consuming app (Blawk's `BlawkMetrics`, Kalendee's +pack CSS, etc.). Regenerate `Palettes.kt` after a token change: + +```bash +python3 compose/scripts/generate_palettes.py packages/themes/dist/tokens.json +``` + +`tokens.json` must include sRGB `hex` per colour key (the preview dump / SNAPSHOT.3 +shape). The twenty oklch tokens in `packages/themes/src/tokens.mjs` remain the +source of truth for CSS and Shiki. + ## Adding a palette 1. Add it to `packages/themes/src/tokens.mjs` (id, label, scheme, `shiki`, and the twenty colour keys). 2. `pnpm --filter @kolektiv/themes build`. -3. Bump the version, add a `CHANGELOG.md` entry, and push a `v*` tag. +3. Regenerate Compose palettes (`python3 compose/scripts/generate_palettes.py`). +4. Bump the version, add a `CHANGELOG.md` entry, and push a `v*` tag. ## Development @@ -53,6 +97,7 @@ pnpm install pnpm typecheck pnpm test pnpm build +./gradlew :themes:jvmTest ``` ## Releases @@ -60,4 +105,4 @@ pnpm build Tag-driven, mirroring Keel: `git tag vX.Y.Z && git push origin vX.Y.Z` runs the Release workflow (GitHub Release from the changelog) and the Publish workflow (publishes to `brand-npm`, then verifies resolution from `npm-public`). -Secrets: `YURI_CAPITAL_REPO_USERNAME`, `YURI_CAPITAL_REPO_PASSWORD`. +Secrets: `YURI_CAPITAL_REPO_USERNAME`, `YURI_CAPITAL_REPO_PASSWORD`. \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..4d53baa --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,10 @@ +plugins { + alias(libs.plugins.kotlinMultiplatform) apply false + alias(libs.plugins.composeMultiplatform) apply false + alias(libs.plugins.composeCompiler) apply false +} + +allprojects { + group = "dev.kolektiv.themes" + version = "0.0.1-SNAPSHOT.3" +} diff --git a/compose/build.gradle.kts b/compose/build.gradle.kts new file mode 100644 index 0000000..73fe5d1 --- /dev/null +++ b/compose/build.gradle.kts @@ -0,0 +1,109 @@ +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.composeMultiplatform) + alias(libs.plugins.composeCompiler) + `maven-publish` +} + +kotlin { + jvm() + iosArm64() + iosSimulatorArm64() + + sourceSets { + commonMain.dependencies { + api(libs.compose.runtime) + api(libs.compose.ui) + } + commonTest.dependencies { + implementation(libs.kotlin.test) + } + } +} + +publishing { + publications { + // KMP creates target publications; add POM metadata to all + } + repositories { + // GitHub Packages (when GITHUB_TOKEN + GITHUB_ACTOR present) + val ghActor = providers.environmentVariable("GITHUB_ACTOR") + val ghToken = providers.environmentVariable("GITHUB_TOKEN") + if (ghActor.isPresent && ghToken.isPresent) { + maven { + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/KolektivComputer/themes") + credentials { + username = ghActor.get() + password = ghToken.get() + } + } + } + + val yuriUser = providers.environmentVariable("YURI_CAPITAL_REPO_USERNAME") + val yuriPass = providers.environmentVariable("YURI_CAPITAL_REPO_PASSWORD") + if (yuriUser.isPresent && yuriPass.isPresent) { + val user = yuriUser.get() + val pass = yuriPass.get() + val versionString = project.version.toString() + val isCanonicalSnapshot = versionString.endsWith("-SNAPSHOT") + val isPrerelease = versionString.contains("SNAPSHOT") + if (isCanonicalSnapshot) { + maven { + name = "yuriSnapshots" + url = uri("https://repo.yuri.capital/repository/maven-snapshots/") + credentials { + username = user + password = pass + } + } + } else if (!isPrerelease) { + maven { + name = "yuriReleases" + url = uri("https://repo.yuri.capital/repository/maven-releases/") + credentials { + username = user + password = pass + } + } + } else { + // Unique pre-release (e.g. 0.0.1-SNAPSHOT.3) — releases/snapshots policy may reject; + // publish to maven-releases with allow or use snapshots host; prefer releases URL and tolerate policy in script. + maven { + name = "yuriReleases" + url = uri("https://repo.yuri.capital/repository/maven-releases/") + credentials { + username = user + password = pass + } + } + } + } + } +} + +publishing.publications.withType().configureEach { + pom { + name.set("Kolektiv Themes (${project.name})") + description.set("Colour-only Kolektiv design tokens for Compose Multiplatform.") + url.set("https://github.com/KolektivComputer/themes") + licenses { + license { + name.set("MIT") + url.set("https://opensource.org/licenses/MIT") + } + } + developers { + developer { + id.set("kolektiv-computer") + name.set("Kolektiv Computing") + organization.set("Kolektiv Computing") + } + } + scm { + url.set("https://github.com/KolektivComputer/themes") + connection.set("scm:git:https://github.com/KolektivComputer/themes.git") + developerConnection.set("scm:git:https://github.com/KolektivComputer/themes.git") + } + } +} diff --git a/compose/scripts/generate_palettes.py b/compose/scripts/generate_palettes.py new file mode 100644 index 0000000..192299f --- /dev/null +++ b/compose/scripts/generate_palettes.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Regenerate Palettes.kt from a tokens.json that includes hex (SNAPSHOT.3+).""" +import json, sys +from pathlib import Path + +def camel(key: str) -> str: + parts = key.split("-") + return parts[0] + "".join(p[:1].upper() + p[1:] for p in parts[1:]) + +def pascal(id: str) -> str: + return "".join(p[:1].upper() + p[1:] for p in id.split("-")) + +def id_camel(id: str) -> str: + p = pascal(id) + return p[:1].lower() + p[1:] + +def hex_to_color(h: str) -> str: + return f"Color(0xFF{h.lstrip('#').upper()})" + +def main() -> None: + src = Path(sys.argv[1] if len(sys.argv) > 1 else "packages/themes/dist/tokens.json") + out = Path(sys.argv[2] if len(sys.argv) > 2 else "compose/src/commonMain/kotlin/dev/kolektiv/themes/Palettes.kt") + tokens = json.loads(src.read_text()) + color_keys = tokens["colorKeys"] + themes = tokens["themes"] + version = tokens["version"] + palette_blocks = [] + object_vals = [] + all_entries = [] + alias_vals = [] + for t in themes: + pid = pascal(t["id"]) + cid = id_camel(t["id"]) + lines = [f" {camel(key)} = {hex_to_color(t['hex'][key])}," for key in color_keys] + palette_blocks.append( + f"/** {t['label']} (`{t['id']}`). */\n" + f"val {pid}Colors = DaisyColors(\n" + "\n".join(lines) + "\n)\n" + ) + object_vals.append(f" val {cid}: DaisyColors = {pid}Colors") + all_entries.append(f' "{t["id"]}" to {cid},') + for alias in t.get("aliases") or []: + acid = id_camel(alias) + alias_vals.append( + f" /** CSS alias `{alias}`. */\n" + f" val {acid}: DaisyColors get() = {cid}" + ) + all_entries.append(f' "{alias}" to {cid},') + text = ( + "package dev.kolektiv.themes\n\n" + "import androidx.compose.ui.graphics.Color\n\n" + f"// generated from @kolektiv/themes {version}\n" + f"// implementation(\"dev.kolektiv.themes:themes:{version}\")\n\n" + + "\n".join(palette_blocks) + + "\nobject KolektivThemes {\n" + + "\n".join(object_vals) + "\n\n" + + "\n".join(alias_vals) + + "\n\n val all: Map = mapOf(\n" + + "\n".join(all_entries) + + "\n )\n\n" + + " fun byId(id: String): DaisyColors =\n" + + " all[id] ?: error(\"unknown Kolektiv theme: $id\")\n" + + "}\n" + ) + out.parent.mkdir(parents=True, exist_ok=True) + out.write_text(text) + print(f"wrote {out} ({len(themes)} palettes)") + +if __name__ == "__main__": + main() diff --git a/compose/src/commonMain/kotlin/dev/kolektiv/themes/DaisyColors.kt b/compose/src/commonMain/kotlin/dev/kolektiv/themes/DaisyColors.kt new file mode 100644 index 0000000..8f89361 --- /dev/null +++ b/compose/src/commonMain/kotlin/dev/kolektiv/themes/DaisyColors.kt @@ -0,0 +1,59 @@ +package dev.kolektiv.themes + +import androidx.compose.runtime.Immutable +import androidx.compose.ui.graphics.Color + +/** + * The twenty daisyUI colour tokens. Colour-only: radii, density and chrome + * belong to the consuming app (Blawk metrics, Kalendee pack CSS, …). + * + * Hex values are the sRGB conversion of the oklch tokens in + * `packages/themes/src/tokens.mjs` / `tokens.json`. + */ +@Immutable +data class DaisyColors( + val base100: Color, + val base200: Color, + val base300: Color, + val baseContent: Color, + val primary: Color, + val primaryContent: Color, + val secondary: Color, + val secondaryContent: Color, + val accent: Color, + val accentContent: Color, + val neutral: Color, + val neutralContent: Color, + val info: Color, + val infoContent: Color, + val success: Color, + val successContent: Color, + val warning: Color, + val warningContent: Color, + val error: Color, + val errorContent: Color, +) + +fun DaisyColors.named(token: String): Color = when (token) { + "primary" -> primary + "secondary" -> secondary + "accent" -> accent + "info" -> info + "success" -> success + "warning" -> warning + "error" -> error + "neutral" -> neutral + else -> primary +} + +fun DaisyColors.contentNamed(token: String): Color = when (token) { + "primary" -> primaryContent + "secondary" -> secondaryContent + "accent" -> accentContent + "info" -> infoContent + "success" -> successContent + "warning" -> warningContent + "error" -> errorContent + "neutral" -> neutralContent + else -> primaryContent +} diff --git a/compose/src/commonMain/kotlin/dev/kolektiv/themes/KolektivTheme.kt b/compose/src/commonMain/kotlin/dev/kolektiv/themes/KolektivTheme.kt new file mode 100644 index 0000000..9200772 --- /dev/null +++ b/compose/src/commonMain/kotlin/dev/kolektiv/themes/KolektivTheme.kt @@ -0,0 +1,33 @@ +package dev.kolektiv.themes + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color + +val LocalDaisyColors = staticCompositionLocalOf { KolektivThemes.kolektivDark } +val LocalContentColor = staticCompositionLocalOf { KolektivThemes.kolektivDark.baseContent } + +object KolektivTheme { + val colors: DaisyColors + @Composable get() = LocalDaisyColors.current + val contentColor: Color + @Composable get() = LocalContentColor.current +} + +@Composable +fun KolektivTheme( + colors: DaisyColors = KolektivThemes.kolektivDark, + content: @Composable () -> Unit, +) { + CompositionLocalProvider( + LocalDaisyColors provides colors, + LocalContentColor provides colors.baseContent, + content = content, + ) +} + +@Composable +fun ProvideContentColor(color: Color, content: @Composable () -> Unit) { + CompositionLocalProvider(LocalContentColor provides color, content = content) +} diff --git a/compose/src/commonMain/kotlin/dev/kolektiv/themes/Palettes.kt b/compose/src/commonMain/kotlin/dev/kolektiv/themes/Palettes.kt new file mode 100644 index 0000000..8e0d30c --- /dev/null +++ b/compose/src/commonMain/kotlin/dev/kolektiv/themes/Palettes.kt @@ -0,0 +1,204 @@ +package dev.kolektiv.themes + +import androidx.compose.ui.graphics.Color + +// generated from @kolektiv/themes 0.0.1-SNAPSHOT.3 +// implementation("dev.kolektiv.themes:themes:0.0.1-SNAPSHOT.3") + +/** Nord (`nord`). */ +val NordColors = DaisyColors( + base100 = Color(0xFFECEFF4), + base200 = Color(0xFFE5E9F0), + base300 = Color(0xFFD8DEE9), + baseContent = Color(0xFF2E3440), + primary = Color(0xFF5E81AC), + primaryContent = Color(0xFF03060B), + secondary = Color(0xFF81A1C1), + secondaryContent = Color(0xFF06090D), + accent = Color(0xFF88C0D0), + accentContent = Color(0xFF070D10), + neutral = Color(0xFF4C566A), + neutralContent = Color(0xFFD8DEE9), + info = Color(0xFFB48EAD), + infoContent = Color(0xFF0C070B), + success = Color(0xFFA3BE8D), + successContent = Color(0xFF0A0D07), + warning = Color(0xFFEBCB8B), + warningContent = Color(0xFF130F07), + error = Color(0xFFBF616A), + errorContent = Color(0xFF0D0304), +) + +/** Catppuccin Latte (`catppuccin-latte`). */ +val CatppuccinLatteColors = DaisyColors( + base100 = Color(0xFFEFF1F5), + base200 = Color(0xFFE6E9EF), + base300 = Color(0xFFCCD0DA), + baseContent = Color(0xFF4C4F69), + primary = Color(0xFF8839EF), + primaryContent = Color(0xFFF9F7FF), + secondary = Color(0xFFDD7878), + secondaryContent = Color(0xFFFFF6F6), + accent = Color(0xFF179299), + accentContent = Color(0xFFE7FEFF), + neutral = Color(0xFFBCC0CC), + neutralContent = Color(0xFF4C4F69), + info = Color(0xFF1F9FB5), + infoContent = Color(0xFFEDFCFF), + success = Color(0xFF40A02B), + successContent = Color(0xFFECFFE8), + warning = Color(0xFFFE640B), + warningContent = Color(0xFFFFF6F3), + error = Color(0xFFD20D39), + errorContent = Color(0xFFFFF6F6), +) + +/** Catppuccin Frappé (`catppuccin-frappe`). */ +val CatppuccinFrappeColors = DaisyColors( + base100 = Color(0xFF232634), + base200 = Color(0xFF292C3C), + base300 = Color(0xFF303446), + baseContent = Color(0xFFC6D0F5), + primary = Color(0xFFCA9EE6), + primaryContent = Color(0xFF240036), + secondary = Color(0xFFEEBEBE), + secondaryContent = Color(0xFF623B3C), + accent = Color(0xFF81C8BE), + accentContent = Color(0xFF00544C), + neutral = Color(0xFF51576D), + neutralContent = Color(0xFFC6D0F5), + info = Color(0xFF85C1DC), + infoContent = Color(0xFF0C4F66), + success = Color(0xFFA6D189), + successContent = Color(0xFF2F5309), + warning = Color(0xFFEF9F76), + warningContent = Color(0xFF753000), + error = Color(0xFFE78284), + errorContent = Color(0xFF7D222B), +) + +/** Catppuccin Macchiato (`catppuccin-macchiato`). */ +val CatppuccinMacchiatoColors = DaisyColors( + base100 = Color(0xFF181926), + base200 = Color(0xFF1E2030), + base300 = Color(0xFF24273A), + baseContent = Color(0xFFCAD3F5), + primary = Color(0xFFC6A0F6), + primaryContent = Color(0xFF21003B), + secondary = Color(0xFFF0C6C6), + secondaryContent = Color(0xFF5F3D3E), + accent = Color(0xFF8AD5CA), + accentContent = Color(0xFF00544C), + neutral = Color(0xFF494D64), + neutralContent = Color(0xFFCAD3F5), + info = Color(0xFF7DC4E4), + infoContent = Color(0xFF004F69), + success = Color(0xFFA6DA95), + successContent = Color(0xFF265413), + warning = Color(0xFFF5A97F), + warningContent = Color(0xFF733200), + error = Color(0xFFED8796), + errorContent = Color(0xFF7C2136), +) + +/** Catppuccin Mocha (`catppuccin-mocha`). */ +val CatppuccinMochaColors = DaisyColors( + base100 = Color(0xFF11111B), + base200 = Color(0xFF181825), + base300 = Color(0xFF1E1E2E), + baseContent = Color(0xFFCDD6F4), + primary = Color(0xFFCBA6F7), + primaryContent = Color(0xFF21003A), + secondary = Color(0xFFF2CDCD), + secondaryContent = Color(0xFF5C3F3F), + accent = Color(0xFF94E2D5), + accentContent = Color(0xFF00544B), + neutral = Color(0xFF45475A), + neutralContent = Color(0xFFCDD6F4), + info = Color(0xFF75C7EC), + infoContent = Color(0xFF004F69), + success = Color(0xFFA6E3A1), + successContent = Color(0xFF1C561A), + warning = Color(0xFFFAB387), + warningContent = Color(0xFF703501), + error = Color(0xFFF38BA8), + errorContent = Color(0xFF7C1F41), +) + +/** Kolektiv Light (`kolektiv-light`). */ +val KolektivLightColors = DaisyColors( + base100 = Color(0xFFFFFFFF), + base200 = Color(0xFFFFE6F9), + base300 = Color(0xFFF2D8EC), + baseContent = Color(0xFF634E5E), + primary = Color(0xFFC494E0), + primaryContent = Color(0xFF250035), + secondary = Color(0xFFD3E094), + secondaryContent = Color(0xFF151800), + accent = Color(0xFF94DEE0), + accentContent = Color(0xFF001B1C), + neutral = Color(0xFFE0B294), + neutralContent = Color(0xFF270F00), + info = Color(0xFF3F84E5), + infoContent = Color(0xFF001436), + success = Color(0xFF03CEA4), + successContent = Color(0xFF001C14), + warning = Color(0xFFCFAA00), + warningContent = Color(0xFF050300), + error = Color(0xFFEF2D56), + errorContent = Color(0xFF0D0001), +) + +/** Kolektiv Dark (`kolektiv-dark`). */ +val KolektivDarkColors = DaisyColors( + base100 = Color(0xFF10030D), + base200 = Color(0xFF23111F), + base300 = Color(0xFF321F2E), + baseContent = Color(0xFFFFEBFA), + primary = Color(0xFFE4C1F9), + primaryContent = Color(0xFF320002), + secondary = Color(0xFFF0FAC3), + secondaryContent = Color(0xFF151800), + accent = Color(0xFFC3F8FA), + accentContent = Color(0xFF001B1C), + neutral = Color(0xFFFAD8C3), + neutralContent = Color(0xFF260F01), + info = Color(0xFF3F84E5), + infoContent = Color(0xFF001436), + success = Color(0xFF03CEA4), + successContent = Color(0xFF001C14), + warning = Color(0xFFEAC434), + warningContent = Color(0xFF1C1500), + error = Color(0xFFEF2D56), + errorContent = Color(0xFF0D0001), +) + +object KolektivThemes { + val nord: DaisyColors = NordColors + val catppuccinLatte: DaisyColors = CatppuccinLatteColors + val catppuccinFrappe: DaisyColors = CatppuccinFrappeColors + val catppuccinMacchiato: DaisyColors = CatppuccinMacchiatoColors + val catppuccinMocha: DaisyColors = CatppuccinMochaColors + val kolektivLight: DaisyColors = KolektivLightColors + val kolektivDark: DaisyColors = KolektivDarkColors + + /** CSS alias `kolektivcomputer-lig`. */ + val kolektivcomputerLig: DaisyColors get() = kolektivLight + /** CSS alias `kolektivcomputer-dark`. */ + val kolektivcomputerDark: DaisyColors get() = kolektivDark + + val all: Map = mapOf( + "nord" to nord, + "catppuccin-latte" to catppuccinLatte, + "catppuccin-frappe" to catppuccinFrappe, + "catppuccin-macchiato" to catppuccinMacchiato, + "catppuccin-mocha" to catppuccinMocha, + "kolektiv-light" to kolektivLight, + "kolektivcomputer-lig" to kolektivLight, + "kolektiv-dark" to kolektivDark, + "kolektivcomputer-dark" to kolektivDark, + ) + + fun byId(id: String): DaisyColors = + all[id] ?: error("unknown Kolektiv theme: $id") +} diff --git a/compose/src/commonTest/kotlin/dev/kolektiv/themes/PalettesTest.kt b/compose/src/commonTest/kotlin/dev/kolektiv/themes/PalettesTest.kt new file mode 100644 index 0000000..59de8ce --- /dev/null +++ b/compose/src/commonTest/kotlin/dev/kolektiv/themes/PalettesTest.kt @@ -0,0 +1,47 @@ +package dev.kolektiv.themes + +import androidx.compose.ui.graphics.Color +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertSame + +class PalettesTest { + @Test + fun sevenBrandPalettes() { + val ids = listOf( + "nord", + "catppuccin-latte", + "catppuccin-frappe", + "catppuccin-macchiato", + "catppuccin-mocha", + "kolektiv-light", + "kolektiv-dark", + ) + assertEquals(ids, ids.filter { KolektivThemes.all.containsKey(it) }) + ids.forEach { id -> assertEquals(KolektivThemes.byId(id), KolektivThemes.all.getValue(id)) } + } + + @Test + fun kolektivDarkHexMatchesTokens() { + val colors = KolektivThemes.kolektivDark + assertEquals(Color(0xFF10030D), colors.base100) + assertEquals(Color(0xFFE4C1F9), colors.primary) + assertEquals(Color(0xFFF0FAC3), colors.secondary) + assertEquals(Color(0xFFC3F8FA), colors.accent) + assertEquals(Color(0xFFEF2D56), colors.error) + } + + @Test + fun kolektivLightHexMatchesTokens() { + assertEquals(Color(0xFFFFFFFF), KolektivThemes.kolektivLight.base100) + assertEquals(Color(0xFFC494E0), KolektivThemes.kolektivLight.primary) + } + + @Test + fun cssAliases() { + assertSame(KolektivThemes.kolektivDark, KolektivThemes.byId("kolektivcomputer-dark")) + assertSame(KolektivThemes.kolektivLight, KolektivThemes.byId("kolektivcomputer-lig")) + assertSame(KolektivThemes.kolektivDark, KolektivThemes.kolektivcomputerDark) + assertSame(KolektivThemes.kolektivLight, KolektivThemes.kolektivcomputerLig) + } +} diff --git a/docs/PUBLISHING.md b/docs/PUBLISHING.md new file mode 100644 index 0000000..f04a5ef --- /dev/null +++ b/docs/PUBLISHING.md @@ -0,0 +1,41 @@ +# Publishing (themes) + +## Targets + +| Ecosystem | Yuri Capital | GitHub Packages | JSR | +| --- | --- | --- | --- | +| Maven (`dev.kolektiv.themes:themes`) | `maven-releases` / `maven-snapshots` | `maven.pkg.github.com/KolektivComputer/themes` | — | +| TypeScript / npm (`` `@kolektiv/themes` ``) | `brand-npm` | `npm.pkg.github.com` | `` `@kolektiv/themes` `` via OIDC | + +GroupId note: Compose module uses `dev.kolektiv.themes` to match current PR coordinates; org epic prefers `computer.kolektiv.*` — migrate in a follow-up. + +## Workflows + +- `publish.yml` on `v*` tags / `workflow_dispatch`: Maven + dual npm + JSR OIDC +- `release.yml`: GitHub Release notes only (same tag) + +## Secrets + +| Name | Purpose | +| --- | --- | +| `YURI_CAPITAL_REPO_USERNAME` / `YURI_CAPITAL_REPO_PASSWORD` | Maven + npm → Yuri Capital | +| `GITHUB_TOKEN` | automatic; needs `packages: write` + `id-token: write` | + +## JSR (org setup) + +**OIDC only in CI** — do not set `JSR_TOKEN` at org level for Actions. + +1. Claim scope `` `@kolektiv` `` on jsr.io (Mey owns it). +2. Create/open package `` `@kolektiv/themes` `` and enable **GitHub Actions trusted publishing** for `KolektivComputer/themes`. +3. Workflow already sets `permissions.id-token: write`. + +PAT/`JSR_TOKEN` is only for local CLI publishes, not org Actions. + +## TypeScript package + +```bash +pnpm install --frozen-lockfile +pnpm typecheck && pnpm test && pnpm build:packages +``` + +Publish scripts: `.github/scripts/publish-npm.sh`, `publish-jsr.sh`. diff --git a/docs/workflow-publish.yml.example b/docs/workflow-publish.yml.example new file mode 100644 index 0000000..57cd5f3 --- /dev/null +++ b/docs/workflow-publish.yml.example @@ -0,0 +1,57 @@ +name: Publish + +on: + workflow_dispatch: + push: + tags: ["v*"] + +permissions: + contents: read + packages: write + id-token: write + +concurrency: + group: publish-${{ github.ref }} + cancel-in-progress: false + +jobs: + maven: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "17" + - uses: gradle/actions/setup-gradle@v4 + - name: Publish Maven + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + YURI_CAPITAL_REPO_USERNAME: ${{ secrets.YURI_CAPITAL_REPO_USERNAME }} + YURI_CAPITAL_REPO_PASSWORD: ${{ secrets.YURI_CAPITAL_REPO_PASSWORD }} + run: bash .github/scripts/publish-maven.sh + + npm: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22" + cache: pnpm + registry-url: https://npm.pkg.github.com + scope: "@kolektiv" + - run: pnpm install --frozen-lockfile + - run: pnpm build:packages + - name: Publish npm (Yuri Capital + GH Packages) + env: + YURI_CAPITAL_REPO_USERNAME: ${{ secrets.YURI_CAPITAL_REPO_USERNAME }} + YURI_CAPITAL_REPO_PASSWORD: ${{ secrets.YURI_CAPITAL_REPO_PASSWORD }} + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bash .github/scripts/publish-npm.sh + - name: Verify npm resolution + run: bash .github/scripts/verify-npm-resolution.sh + - name: Publish JSR (OIDC) + run: bash .github/scripts/publish-jsr.sh diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..682c03e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,5 @@ +kotlin.code.style=official +org.gradle.jvmargs=-Xmx2g +org.gradle.parallel=true +org.jetbrains.compose.experimental.jscanvas.enabled=true +android.useAndroidX=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..c1f3526 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,13 @@ +[versions] +composeMultiplatform = "1.12.0" +kotlin = "2.4.20" + +[libraries] +kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } +compose-runtime = { module = "org.jetbrains.compose.runtime:runtime", version.ref = "composeMultiplatform" } +compose-ui = { module = "org.jetbrains.compose.ui:ui", version.ref = "composeMultiplatform" } + +[plugins] +kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" } +composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..8bdaf60 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..d4081da --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..adff685 --- /dev/null +++ b/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100755 index 0000000..e509b2d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,93 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/packages/themes/jsr.json b/packages/themes/jsr.json new file mode 100644 index 0000000..6c9294d --- /dev/null +++ b/packages/themes/jsr.json @@ -0,0 +1,13 @@ +{ + "name": "@kolektiv/themes", + "version": "0.0.1-SNAPSHOT.3", + "exports": "./dist/index.mjs", + "publish": { + "include": [ + "dist", + "jsr.json", + "README.md", + "LICENSE" + ] + } +} diff --git a/packages/themes/package.json b/packages/themes/package.json index a5c24e6..dc0b0b3 100644 --- a/packages/themes/package.json +++ b/packages/themes/package.json @@ -1,6 +1,6 @@ { "name": "@kolektiv/themes", - "version": "0.0.1-SNAPSHOT.2", + "version": "0.0.1-SNAPSHOT.3", "description": "Colour-only Kolektiv design tokens and generated themes (daisyUI, Shiki, Compose).", "license": "MIT", "type": "module", diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..05eadd4 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,36 @@ +rootProject.name = "kolektiv-themes" + +pluginManagement { + repositories { + google { + mavenContent { + includeGroupAndSubgroups("androidx") + includeGroupAndSubgroups("com.android") + includeGroupAndSubgroups("com.google") + } + } + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositories { + google { + mavenContent { + includeGroupAndSubgroups("androidx") + includeGroupAndSubgroups("com.android") + includeGroupAndSubgroups("com.google") + } + } + mavenCentral() + maven("https://repo.yuri.capital/repository/maven-releases/") + } +} + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} + +include(":themes") +project(":themes").projectDir = file("compose")