diff --git a/AGENTS.md b/AGENTS.md index 1a16e0c..d20ad7c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -99,14 +99,14 @@ Configuration in `netlify.toml`. ``` src/ -├── components/ # Svelte components -├── layouts/ # Astro layouts -├── lib/ # Utilities, UI components -├── pages/ # Astro routes (*.astro) -├── services/ # Business logic -└── types/ # TypeScript types -tests/ # Playwright e2e specs -netlify/functions/ # Netlify serverless functions +├── components/ # Svelte components, each in [Name]/[Name].svelte +├── layouts/ # Astro layouts (MainLayout.astro) +├── lib/ # Utilities, UI components +├── pages/ # Astro routes (*.astro) +├── services/ # Business logic +└── types/ # TypeScript types +tests/ # Playwright e2e specs +netlify/functions/ # Netlify serverless functions ``` ## State Management @@ -123,7 +123,7 @@ Uses Svelte 5's `$state` runes with context-based sharing. ### Architecture Pattern -1. **Root component** (`transliterate/index.svelte`) creates state with `$state()` and exposes it via Svelte context using `setContext>("state_key", ...)` +1. **Root component** (e.g. `Transliterate/Transliterate.svelte`) creates state with `$state()` and exposes it via Svelte context using `setContext>("state_key", ...)` 2. **Consumer components** access state via `getContext>("state_key")` and mutate directly via `.value` property diff --git a/netlify.toml b/netlify.toml index e67f173..ab8bc8c 100644 --- a/netlify.toml +++ b/netlify.toml @@ -14,3 +14,14 @@ for = "/schemas/*" [headers.values] Cache-Control = "public, max-age=31536000, immutable" + +[[headers]] + for = "/*" + [headers.values] + Accept-CH = "Sec-CH-Prefers-Color-Scheme" + Critical-CH = "Sec-CH-Prefers-Color-Scheme" + Vary = "Sec-CH-Prefers-Color-Scheme" + +[[edge_functions]] + function = "check-theme" + path = "/*" diff --git a/netlify/edge-functions/check-theme.ts b/netlify/edge-functions/check-theme.ts new file mode 100644 index 0000000..9834636 --- /dev/null +++ b/netlify/edge-functions/check-theme.ts @@ -0,0 +1,24 @@ +import type { Config, Context } from "@netlify/edge-functions"; + +export default async (request: Request, context: Context) => { + const response = await context.next(); + + const contentType = response.headers.get("content-type"); + if (!contentType || !contentType.includes("text/html")) { + return response; + } + + let html = await response.text(); + + const theme = context.cookies.get("theme") || "system"; + html = html.replace("{{ USER_THEME }}", theme); + + return new Response(html, { + status: response.status, + headers: response.headers, + }); +}; + +export const config: Config = { + path: "/*", +}; diff --git a/package-lock.json b/package-lock.json index 22e375e..2889906 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@astrojs/netlify": "^8.0.0", "@astrojs/svelte": "^9.0.0", "@codemirror/lang-javascript": "^6.2.5", + "@tabler/icons-astro": "^3.46.0", "@tabler/icons-svelte": "^3.44.0", "@tailwindcss/vite": "^4.3.1", "astro": "^7.0.0", @@ -26,16 +27,16 @@ "devDependencies": { "@eslint/js": "^10.0.1", "@internationalized/date": "^3.12.2", - "@lucide/svelte": "^1.21.0", + "@lucide/svelte": "^1.27.0", "@netlify/functions": "^5.3.0", "@playwright/test": "^1.61.0", "@types/node": "^26.0.0", + "@types/serialize-javascript": "^5.0.4", "bits-ui": "^2.18.1", "clsx": "^2.1.1", "eslint": "^10.5.0", "eslint-plugin-svelte": "^3.19.0", "globals": "^17.7.0", - "mode-watcher": "^1.1.0", "npm-check-updates": "^22.2.7", "prettier": "^3.8.4", "prettier-plugin-astro": "^0.14.1", @@ -2539,9 +2540,9 @@ } }, "node_modules/@lucide/svelte": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-1.21.0.tgz", - "integrity": "sha512-MEv//A7Jv3kHukZowv/DWp1MAtUzJKYwtJsmnQ7X98lCgtac3z3NbaToDl3Q6jO3gS9sougFpcD+t+YuxOkRMw==", + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-1.27.0.tgz", + "integrity": "sha512-qzNBHdqy/MKp2qxuy/DcYELuep6h19fjo+4ech8fZsS4GtZeBtg5jgCTRQvLvwhppt0mhRN6qt8Nt8rPb/J4Ag==", "dev": true, "license": "ISC", "peerDependencies": { @@ -4536,6 +4537,32 @@ "url": "https://github.com/sponsors/codecalm" } }, + "node_modules/@tabler/icons-astro": { + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/@tabler/icons-astro/-/icons-astro-3.46.0.tgz", + "integrity": "sha512-hLbPYqiVOAe6SPNRnXyMCmeVJpcqoIiXDqlMjb2deMdhZXZU6FSOtUVUG08T6zBYXqP0CieZZAkvrFgIFHfeCg==", + "license": "MIT", + "dependencies": { + "@tabler/icons": "3.46.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + }, + "peerDependencies": { + "astro": ">=4.0.0" + } + }, + "node_modules/@tabler/icons-astro/node_modules/@tabler/icons": { + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.46.0.tgz", + "integrity": "sha512-f2RYFl3fzPwj5WO82x6en0dmkjefxEfOm16D1ByM6cj/McNiwOkL4VaPUoP9VVIrXAD9WnTSVFr70px703b//A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + } + }, "node_modules/@tabler/icons-svelte": { "version": "3.44.0", "resolved": "https://registry.npmjs.org/@tabler/icons-svelte/-/icons-svelte-3.44.0.tgz", @@ -4897,6 +4924,13 @@ "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", "license": "MIT" }, + "node_modules/@types/serialize-javascript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/serialize-javascript/-/serialize-javascript-5.0.4.tgz", + "integrity": "sha512-Z2R7UKFuNWCP8eoa2o9e5rkD3hmWxx/1L0CYz0k2BZzGh0PhEVMp9kfGiqEml/0IglwNERXZ2hwNzIrSz/KHTA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/triple-beam": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", @@ -10907,73 +10941,6 @@ "ufo": "^1.6.3" } }, - "node_modules/mode-watcher": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-1.1.0.tgz", - "integrity": "sha512-mUT9RRGPDYenk59qJauN1rhsIMKBmWA3xMF+uRwE8MW/tjhaDSCCARqkSuDTq8vr4/2KcAxIGVjACxTjdk5C3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "runed": "^0.25.0", - "svelte-toolbelt": "^0.7.1" - }, - "peerDependencies": { - "svelte": "^5.27.0" - } - }, - "node_modules/mode-watcher/node_modules/runed": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.25.0.tgz", - "integrity": "sha512-7+ma4AG9FT2sWQEA0Egf6mb7PBT2vHyuHail1ie8ropfSjvZGtEAx8YTmUjv/APCsdRRxEVvArNjALk9zFSOrg==", - "dev": true, - "funding": [ - "https://github.com/sponsors/huntabyte", - "https://github.com/sponsors/tglide" - ], - "dependencies": { - "esm-env": "^1.0.0" - }, - "peerDependencies": { - "svelte": "^5.7.0" - } - }, - "node_modules/mode-watcher/node_modules/svelte-toolbelt": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.7.1.tgz", - "integrity": "sha512-HcBOcR17Vx9bjaOceUvxkY3nGmbBmCBBbuWLLEWO6jtmWH8f/QoWmbyUfQZrpDINH39en1b8mptfPQT9VKQ1xQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/huntabyte" - ], - "dependencies": { - "clsx": "^2.1.1", - "runed": "^0.23.2", - "style-to-object": "^1.0.8" - }, - "engines": { - "node": ">=18", - "pnpm": ">=8.7.0" - }, - "peerDependencies": { - "svelte": "^5.0.0" - } - }, - "node_modules/mode-watcher/node_modules/svelte-toolbelt/node_modules/runed": { - "version": "0.23.4", - "resolved": "https://registry.npmjs.org/runed/-/runed-0.23.4.tgz", - "integrity": "sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA==", - "dev": true, - "funding": [ - "https://github.com/sponsors/huntabyte", - "https://github.com/sponsors/tglide" - ], - "dependencies": { - "esm-env": "^1.0.0" - }, - "peerDependencies": { - "svelte": "^5.7.0" - } - }, "node_modules/module-definition": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-6.0.2.tgz", diff --git a/package.json b/package.json index 8d3f30b..197ba8f 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@astrojs/netlify": "^8.0.0", "@astrojs/svelte": "^9.0.0", "@codemirror/lang-javascript": "^6.2.5", + "@tabler/icons-astro": "^3.46.0", "@tabler/icons-svelte": "^3.44.0", "@tailwindcss/vite": "^4.3.1", "astro": "^7.0.0", @@ -42,16 +43,16 @@ "devDependencies": { "@eslint/js": "^10.0.1", "@internationalized/date": "^3.12.2", - "@lucide/svelte": "^1.21.0", + "@lucide/svelte": "^1.27.0", "@netlify/functions": "^5.3.0", "@playwright/test": "^1.61.0", "@types/node": "^26.0.0", + "@types/serialize-javascript": "^5.0.4", "bits-ui": "^2.18.1", "clsx": "^2.1.1", "eslint": "^10.5.0", "eslint-plugin-svelte": "^3.19.0", "globals": "^17.7.0", - "mode-watcher": "^1.1.0", "npm-check-updates": "^22.2.7", "prettier": "^3.8.4", "prettier-plugin-astro": "^0.14.1", diff --git a/playwright.config.ts b/playwright.config.ts index c0b8e84..3654f71 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ timeout: 10000, }, webServer: { - command: "npm run dev", + command: "NETLIFY_DEV=1 npm run dev", port: 4321, reuseExistingServer: false, timeout: 120 * 1000, diff --git a/src/components/shared/Card.svelte b/src/components/Card/Card.svelte similarity index 95% rename from src/components/shared/Card.svelte rename to src/components/Card/Card.svelte index f51d824..77c98b7 100644 --- a/src/components/shared/Card.svelte +++ b/src/components/Card/Card.svelte @@ -3,7 +3,7 @@ import { Separator } from "$lib/components/ui/separator/index.js"; import { version } from "hebrew-transliteration/package.json"; import type { Snippet } from "svelte"; - import FeedbackModal from "./FeedbackModal.svelte"; + import FeedbackModal from "../FeedbackModal/FeedbackModal.svelte"; interface Props { aria_busy: boolean; diff --git a/src/components/shared/Dialog.svelte b/src/components/Dialog/Dialog.svelte similarity index 100% rename from src/components/shared/Dialog.svelte rename to src/components/Dialog/Dialog.svelte diff --git a/src/components/shared/ErrorBoundary.svelte b/src/components/ErrorBoundary/ErrorBoundary.svelte similarity index 100% rename from src/components/shared/ErrorBoundary.svelte rename to src/components/ErrorBoundary/ErrorBoundary.svelte diff --git a/src/components/shared/FeedbackModal.svelte b/src/components/FeedbackModal/FeedbackModal.svelte similarity index 100% rename from src/components/shared/FeedbackModal.svelte rename to src/components/FeedbackModal/FeedbackModal.svelte diff --git a/src/components/shared/Input.svelte b/src/components/Input/Input.svelte similarity index 100% rename from src/components/shared/Input.svelte rename to src/components/Input/Input.svelte diff --git a/src/layouts/Navigation.astro b/src/components/Navigation/Navigation.astro similarity index 97% rename from src/layouts/Navigation.astro rename to src/components/Navigation/Navigation.astro index 81820ef..8a472c7 100644 --- a/src/layouts/Navigation.astro +++ b/src/components/Navigation/Navigation.astro @@ -1,5 +1,5 @@ --- -import NavigationLink from "./NavigationLink.astro"; +import NavigationLink from "../NavigationLink/NavigationLink.astro"; const links = [ { label: "Transliterate", href: "/" }, diff --git a/src/layouts/NavigationLink.astro b/src/components/NavigationLink/NavigationLink.astro similarity index 100% rename from src/layouts/NavigationLink.astro rename to src/components/NavigationLink/NavigationLink.astro diff --git a/src/components/shared/Output.svelte b/src/components/Output/Output.svelte similarity index 100% rename from src/components/shared/Output.svelte rename to src/components/Output/Output.svelte diff --git a/src/components/remove/index.svelte b/src/components/Remove/Remove.svelte similarity index 97% rename from src/components/remove/index.svelte rename to src/components/Remove/Remove.svelte index f507bee..44a87af 100644 --- a/src/components/remove/index.svelte +++ b/src/components/Remove/Remove.svelte @@ -10,9 +10,9 @@ import { performRemoval } from "../../services/removalService"; import type { AppStatus, Context, RemoveState } from "../../types/index"; import { default_remove_options } from "../../utils/defaults"; - import Card from "../shared/Card.svelte"; - import Input from "../shared/Input.svelte"; - import Output from "../shared/Output.svelte"; + import Card from "../Card/Card.svelte"; + import Input from "../Input/Input.svelte"; + import Output from "../Output/Output.svelte"; import Settings from "./Settings.svelte"; const saved_options = deserialize_object( diff --git a/src/components/remove/Settings.svelte b/src/components/Remove/Settings.svelte similarity index 99% rename from src/components/remove/Settings.svelte rename to src/components/Remove/Settings.svelte index 0ca134e..4cad8f1 100644 --- a/src/components/remove/Settings.svelte +++ b/src/components/Remove/Settings.svelte @@ -14,7 +14,7 @@ import CodeMirror from "svelte-codemirror-editor"; import type { Context, RemoveState } from "../../types/index"; import { format_doc_url } from "../../utils/documentation"; - import Dialog from "../shared/Dialog.svelte"; + import Dialog from "../Dialog/Dialog.svelte"; const remove_state = getContext>("remove_state"); diff --git a/src/layouts/SchemaOrg.astro b/src/components/SchemaOrg/SchemaOrg.astro similarity index 100% rename from src/layouts/SchemaOrg.astro rename to src/components/SchemaOrg/SchemaOrg.astro diff --git a/src/components/structure/Settings.svelte b/src/components/Structure/Settings.svelte similarity index 98% rename from src/components/structure/Settings.svelte rename to src/components/Structure/Settings.svelte index 8ff64ac..a4e26b9 100644 --- a/src/components/structure/Settings.svelte +++ b/src/components/Structure/Settings.svelte @@ -8,7 +8,7 @@ import { getContext } from "svelte"; import type { WhitespaceOption } from "../../services/structureService"; import type { Context, StructureState } from "../../types/index"; - import Dialog from "../shared/Dialog.svelte"; + import Dialog from "../Dialog/Dialog.svelte"; const structure_state = getContext>("structure_state"); diff --git a/src/components/structure/index.svelte b/src/components/Structure/Structure.svelte similarity index 96% rename from src/components/structure/index.svelte rename to src/components/Structure/Structure.svelte index 707c2fc..07aa66e 100644 --- a/src/components/structure/index.svelte +++ b/src/components/Structure/Structure.svelte @@ -8,9 +8,9 @@ import { performStructure } from "../../services/structureService"; import type { AppStatus, Context, StructureState } from "../../types/index"; import { default_structure_options } from "../../utils/defaults"; - import Card from "../shared/Card.svelte"; - import Input from "../shared/Input.svelte"; - import Output from "../shared/Output.svelte"; + import Card from "../Card/Card.svelte"; + import Input from "../Input/Input.svelte"; + import Output from "../Output/Output.svelte"; import Settings from "./Settings.svelte"; const saved_options = load_settings(STORAGE_KEYS.structure, default_structure_options); diff --git a/src/components/ThemeSelector/ThemeSelector.svelte b/src/components/ThemeSelector/ThemeSelector.svelte new file mode 100644 index 0000000..b9ddc67 --- /dev/null +++ b/src/components/ThemeSelector/ThemeSelector.svelte @@ -0,0 +1,28 @@ + + + + + + + set_display("light")}>Light + set_display("dark")}>Dark + set_display("system")}>System + + diff --git a/src/components/transliterate/FeatureEditor.svelte b/src/components/Transliterate/FeatureEditor.svelte similarity index 100% rename from src/components/transliterate/FeatureEditor.svelte rename to src/components/Transliterate/FeatureEditor.svelte diff --git a/src/components/transliterate/KetivQereEditor.svelte b/src/components/Transliterate/KetivQereEditor.svelte similarity index 100% rename from src/components/transliterate/KetivQereEditor.svelte rename to src/components/Transliterate/KetivQereEditor.svelte diff --git a/src/components/transliterate/NiqqudModal.svelte b/src/components/Transliterate/NiqqudModal.svelte similarity index 100% rename from src/components/transliterate/NiqqudModal.svelte rename to src/components/Transliterate/NiqqudModal.svelte diff --git a/src/components/transliterate/SettingsDialog.svelte b/src/components/Transliterate/SettingsDialog.svelte similarity index 99% rename from src/components/transliterate/SettingsDialog.svelte rename to src/components/Transliterate/SettingsDialog.svelte index 4d8beff..9100eb9 100644 --- a/src/components/transliterate/SettingsDialog.svelte +++ b/src/components/Transliterate/SettingsDialog.svelte @@ -37,7 +37,7 @@ import type { Context, TransliterationState, VisibilityState } from "../../types/index"; import { format_doc_url, format_label } from "../../utils/documentation"; import { get_default_SBL_schema } from "../../utils/schemaDefaults"; - import Dialog from "../shared/Dialog.svelte"; + import Dialog from "../Dialog/Dialog.svelte"; import FeatureEditor from "./FeatureEditor.svelte"; import KetivQereEditor from "./KetivQereEditor.svelte"; diff --git a/src/components/transliterate/index.svelte b/src/components/Transliterate/Transliterate.svelte similarity index 97% rename from src/components/transliterate/index.svelte rename to src/components/Transliterate/Transliterate.svelte index 2337b9f..8621d43 100644 --- a/src/components/transliterate/index.svelte +++ b/src/components/Transliterate/Transliterate.svelte @@ -9,10 +9,10 @@ import { performTransliteration as perform_transliteration } from "../../services/transliterationService"; import type { AppStatus, Context, TransliterationState } from "../../types/index"; import { get_default_SBL_schema } from "../../utils/schemaDefaults"; - import Card from "../shared/Card.svelte"; - import ErrorBoundary from "../shared/ErrorBoundary.svelte"; - import Input from "../shared/Input.svelte"; - import Output from "../shared/Output.svelte"; + import Card from "../Card/Card.svelte"; + import ErrorBoundary from "../ErrorBoundary/ErrorBoundary.svelte"; + import Input from "../Input/Input.svelte"; + import Output from "../Output/Output.svelte"; import NiqqudModal from "./NiqqudModal.svelte"; import Settings from "./SettingsDialog.svelte"; diff --git a/src/components/transliterate/utils/schemaCompletion.ts b/src/components/Transliterate/utils/schemaCompletion.ts similarity index 100% rename from src/components/transliterate/utils/schemaCompletion.ts rename to src/components/Transliterate/utils/schemaCompletion.ts diff --git a/src/layouts/MainLayout.astro b/src/layouts/MainLayout.astro index 8d8aaa1..b0f79c2 100644 --- a/src/layouts/MainLayout.astro +++ b/src/layouts/MainLayout.astro @@ -1,7 +1,8 @@ --- import { Toaster } from "$lib/components/ui/sonner/index.js"; import "../styles/global.css"; -import Navigation from "./Navigation.astro"; +import Navigation from "../components/Navigation/Navigation.astro"; +import ThemeSelector from "../components/ThemeSelector/ThemeSelector.svelte"; interface Props { title: string; @@ -22,11 +23,12 @@ const canonicalUrl = new URL( --- - + + @@ -46,6 +48,7 @@ const canonicalUrl = new URL( + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte new file mode 100644 index 0000000..3039589 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,44 @@ + + + + {#snippet children({ checked, indeterminate })} + + {#if indeterminate} + + {:else if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte new file mode 100644 index 0000000..810eb1e --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte new file mode 100644 index 0000000..6300ce4 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte @@ -0,0 +1,22 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte new file mode 100644 index 0000000..2172000 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte new file mode 100644 index 0000000..abb24be --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte new file mode 100644 index 0000000..83c3072 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,27 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte new file mode 100644 index 0000000..f9e1e2a --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte new file mode 100644 index 0000000..d4bbe25 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte new file mode 100644 index 0000000..79e6974 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,34 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte new file mode 100644 index 0000000..7f2b04c --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte new file mode 100644 index 0000000..3c568e6 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte new file mode 100644 index 0000000..db056c3 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte new file mode 100644 index 0000000..95c152e --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte new file mode 100644 index 0000000..35d8094 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte new file mode 100644 index 0000000..bb88efd --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte new file mode 100644 index 0000000..dc3ecf8 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/index.ts b/src/lib/components/ui/dropdown-menu/index.ts new file mode 100644 index 0000000..5c4fe0c --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/index.ts @@ -0,0 +1,54 @@ +import Root from "./dropdown-menu.svelte"; +import Sub from "./dropdown-menu-sub.svelte"; +import CheckboxGroup from "./dropdown-menu-checkbox-group.svelte"; +import CheckboxItem from "./dropdown-menu-checkbox-item.svelte"; +import Content from "./dropdown-menu-content.svelte"; +import Group from "./dropdown-menu-group.svelte"; +import Item from "./dropdown-menu-item.svelte"; +import Label from "./dropdown-menu-label.svelte"; +import RadioGroup from "./dropdown-menu-radio-group.svelte"; +import RadioItem from "./dropdown-menu-radio-item.svelte"; +import Separator from "./dropdown-menu-separator.svelte"; +import Shortcut from "./dropdown-menu-shortcut.svelte"; +import Trigger from "./dropdown-menu-trigger.svelte"; +import SubContent from "./dropdown-menu-sub-content.svelte"; +import SubTrigger from "./dropdown-menu-sub-trigger.svelte"; +import GroupHeading from "./dropdown-menu-group-heading.svelte"; +import Portal from "./dropdown-menu-portal.svelte"; + +export { + CheckboxGroup, + CheckboxItem, + Content, + Portal, + Root as DropdownMenu, + CheckboxGroup as DropdownMenuCheckboxGroup, + CheckboxItem as DropdownMenuCheckboxItem, + Content as DropdownMenuContent, + Portal as DropdownMenuPortal, + Group as DropdownMenuGroup, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + RadioGroup as DropdownMenuRadioGroup, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + Shortcut as DropdownMenuShortcut, + Sub as DropdownMenuSub, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + Trigger as DropdownMenuTrigger, + GroupHeading as DropdownMenuGroupHeading, + Group, + GroupHeading, + Item, + Label, + RadioGroup, + RadioItem, + Root, + Separator, + Shortcut, + Sub, + SubContent, + SubTrigger, + Trigger, +}; diff --git a/src/lib/components/ui/sonner/sonner.svelte b/src/lib/components/ui/sonner/sonner.svelte index 0437784..aca84a1 100644 --- a/src/lib/components/ui/sonner/sonner.svelte +++ b/src/lib/components/ui/sonner/sonner.svelte @@ -1,17 +1,15 @@

Hebrew Transliteration

- This web app transliterates Hebrew text into any output. It's powered by the open-source + This web app transliterates Hebrew text into any output. It's powered by the open-source{ + " " + } hebrew-transliteration + rel="noopener noreferrer">hebrew-transliteration{" "} JavaScript package and supports multiple transliteration schemas — including SBL academic style, Brill, and fully custom mappings.

@@ -47,7 +50,7 @@ const keywords = [

Transliteration converts texts from one script to another, making the text readable to those unfamiliar with the Hebrew script. It's widely used in biblical scholarship, - liturgy, linguistics, and language education. + liturgy, linguistics, and language education.{" "} -

+ diff --git a/src/pages/index.astro b/src/pages/index.astro index 583d582..3efe981 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,7 +1,7 @@ --- -import Transliterate from "../components/transliterate/index.svelte"; +import SchemaOrg from "../components/SchemaOrg/SchemaOrg.astro"; +import Transliterate from "../components/Transliterate/Transliterate.svelte"; import MainLayout from "../layouts/MainLayout.astro"; -import SchemaOrg from "../layouts/SchemaOrg.astro"; import "../styles/global.css"; const title = "Hebrew Transliteration App"; diff --git a/src/pages/remove.astro b/src/pages/remove.astro index 88ec8ce..12bae11 100644 --- a/src/pages/remove.astro +++ b/src/pages/remove.astro @@ -1,7 +1,7 @@ --- -import RemoveComponent from "../components/remove/index.svelte"; +import RemoveComponent from "../components/Remove/Remove.svelte"; import MainLayout from "../layouts/MainLayout.astro"; -import SchemaOrg from "../layouts/SchemaOrg.astro"; +import SchemaOrg from "../components/SchemaOrg/SchemaOrg.astro"; import "../styles/global.css"; const title = "Remove"; diff --git a/src/pages/structure.astro b/src/pages/structure.astro index 2783e75..a0e586a 100644 --- a/src/pages/structure.astro +++ b/src/pages/structure.astro @@ -1,7 +1,7 @@ --- -import StructureComponent from "../components/structure/index.svelte"; +import SchemaOrg from "../components/SchemaOrg/SchemaOrg.astro"; +import StructureComponent from "../components/Structure/Structure.svelte"; import MainLayout from "../layouts/MainLayout.astro"; -import SchemaOrg from "../layouts/SchemaOrg.astro"; import "../styles/global.css"; const title = "Structure"; diff --git a/src/styles/global.css b/src/styles/global.css index 0924cd7..5b640fd 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -2,74 +2,58 @@ @import "tw-animate-css"; +@custom-variant dark (@container style(--theme: dark)); + :root { --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); + color-scheme: light dark; + --theme: light; + --background: light-dark(oklch(1 0 0), oklch(0.145 0 0)); + --foreground: light-dark(oklch(0.145 0 0), oklch(0.985 0 0)); + --card: light-dark(oklch(1 0 0), oklch(0.205 0 0)); + --card-foreground: light-dark(oklch(0.145 0 0), oklch(0.985 0 0)); + --popover: light-dark(oklch(1 0 0), oklch(0.205 0 0)); + --popover-foreground: light-dark(oklch(0.145 0 0), oklch(0.985 0 0)); + --primary: light-dark(oklch(0.205 0 0), oklch(0.922 0 0)); + --primary-foreground: light-dark(oklch(0.985 0 0), oklch(0.205 0 0)); + --secondary: light-dark(oklch(0.97 0 0), oklch(0.269 0 0)); + --secondary-foreground: light-dark(oklch(0.205 0 0), oklch(0.985 0 0)); + --muted: light-dark(oklch(0.97 0 0), oklch(0.269 0 0)); + --muted-foreground: light-dark(oklch(0.556 0 0), oklch(0.708 0 0)); + --accent: light-dark(oklch(0.97 0 0), oklch(0.269 0 0)); + --accent-foreground: light-dark(oklch(0.205 0 0), oklch(0.985 0 0)); + --destructive: light-dark(oklch(0.577 0.245 27.325), oklch(0.704 0.191 22.216)); + --border: light-dark(oklch(0.922 0 0), oklch(1 0 0 / 10%)); + --input: light-dark(oklch(0.922 0 0), oklch(1 0 0 / 15%)); + --ring: light-dark(oklch(0.708 0 0), oklch(0.556 0 0)); + --chart-1: light-dark(oklch(0.646 0.222 41.116), oklch(0.488 0.243 264.376)); + --chart-2: light-dark(oklch(0.6 0.118 184.704), oklch(0.696 0.17 162.48)); + --chart-3: light-dark(oklch(0.398 0.07 227.392), oklch(0.769 0.188 70.08)); + --chart-4: light-dark(oklch(0.828 0.189 84.429), oklch(0.627 0.265 303.9)); + --chart-5: light-dark(oklch(0.769 0.188 70.08), oklch(0.645 0.246 16.439)); + --sidebar: light-dark(oklch(0.985 0 0), oklch(0.205 0 0)); + --sidebar-foreground: light-dark(oklch(0.145 0 0), oklch(0.985 0 0)); + --sidebar-primary: light-dark(oklch(0.205 0 0), oklch(0.488 0.243 264.376)); + --sidebar-primary-foreground: light-dark(oklch(0.985 0 0), oklch(0.985 0 0)); + --sidebar-accent: light-dark(oklch(0.97 0 0), oklch(0.269 0 0)); + --sidebar-accent-foreground: light-dark(oklch(0.205 0 0), oklch(0.985 0 0)); + --sidebar-border: light-dark(oklch(0.922 0 0), oklch(1 0 0 / 10%)); + --sidebar-ring: light-dark(oklch(0.708 0 0), oklch(0.556 0 0)); +} + +:root[data-theme="light"] { + color-scheme: light; + --theme: light; +} + +:root[data-theme="dark"] { + color-scheme: dark; + --theme: dark; } -@media (prefers-color-scheme: dark) { - :root { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); +:root[data-theme="system"] { + @media (prefers-color-scheme: dark) { + --theme: dark; } } diff --git a/tsconfig.json b/tsconfig.json index 8c96c93..1660885 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,9 +3,9 @@ "include": [".astro/types.d.ts", "**/*"], "exclude": ["dist"], "compilerOptions": { - // ... - "baseUrl": ".", "paths": { + // A new catch-all that replaces the baseUrl: + "*": ["./src/*"], "$lib": ["./src/lib"], "$lib/*": ["./src/lib/*"] }