Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
126fa14
Create project
Jul 5, 2025
3f3fc14
Select language card
Jul 6, 2025
214689a
Select and deselect scripts
Jul 6, 2025
378771c
Refactor state management
Aug 30, 2025
4be8195
Add unique IDs to view models
Aug 30, 2025
83f8477
Create language chooser view model
Aug 30, 2025
90e446e
Adds tag preview
Aug 30, 2025
99e9fb0
Adds display name
Aug 30, 2025
d8a6812
Add search text
Aug 30, 2025
568c57b
Make language and script lists reactive
Aug 30, 2025
f9303aa
Clear search results
Aug 30, 2025
c9cf4c2
Correct tag preview when no language selected
Aug 30, 2025
decb47f
Expose selected script and language
Aug 30, 2025
0713fdb
Automatically select a language's only script
Sep 1, 2025
e938459
Allow creating unlisted language
Sep 1, 2025
47d8025
Add cases for clearing selections
Sep 1, 2025
7c69a21
Improve a method signature
Sep 1, 2025
2398017
Allow customizing selected language
Sep 1, 2025
3450b50
Allow entering custom language tag
Sep 1, 2025
4957ef1
Refine Field API
Sep 1, 2025
8abe0f2
Add isReadyToSubmit
Sep 1, 2025
8afe6cd
Refactor for clarity
Sep 1, 2025
6eab6bb
Separate state management into new project
Sep 1, 2025
764f102
Add state-management-svelte project
Sep 1, 2025
fa4d014
Remove unused import
Sep 2, 2025
c5702e9
Implement useViewModel for Svelte 5
Sep 2, 2025
c7de333
Make Field.onUpdate explicitly public
Sep 2, 2025
d7994aa
Refactor selectItem for clarity
Sep 2, 2025
ccca4dc
Add a blank Svelte 5 project
gmjgeek Mar 13, 2025
dbc7080
Install DaisyUI for svelte app
Sep 16, 2025
c7db596
Rename svelte demo project
Sep 16, 2025
c825c2a
Delete unused files
Sep 16, 2025
b6edcc8
Scaffold UI for Svelte demo app
Sep 16, 2025
e9cf2f0
Use view model in Svelte demo app
Sep 17, 2025
d3f72ff
Implement more UI elements
Sep 18, 2025
dc673a2
Return selected language from modal
Sep 20, 2025
a33f054
Implement customization modal
Sep 20, 2025
3bee4a1
Add a temporary hack for customization modal
Sep 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"recommendations": ["ms-playwright.playwright"]
"recommendations": ["ms-playwright.playwright", "esbenp.prettier-vscode"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./src/view-models/language-card";
export * from "./src/view-models/script-card";
export * from "./src/view-models/language-chooser";
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@ethnolib/language-chooser-controller",
"description": "A framework-agnostic controller for a language chooser",
"author": "SIL Global",
"license": "MIT",
"version": "0.1.0",
"main": "./index.js",
"types": "./index.d.ts",
"scripts": {
"build": "nx vite:build",
"typecheck": "tsc",
"test": "nx vite:test --config vitest.config.ts",
"testonce": "nx vite:test --config vitest.config.ts --run",
"lint": "eslint ."
},
"devDependencies": {
"@nx/vite": "^19.1.2",
"@types/node": "^20.16.11",
"tsx": "^4.19.2",
"typescript": "^5.2.2"
},
"volta": {
"extends": "../../../../package.json"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Field } from "@ethnolib/state-management-core";

export interface Selectable {
isSelected: Field<boolean>;
}

export function selectItem(index: number, items: Selectable[]) {
items.forEach((item, i) => {
item.isSelected.value = i === index;
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ILanguage } from "@ethnolib/find-language";
import { Field } from "@ethnolib/state-management-core";
import { Selectable } from "../selectable";
import { LanguageChooserTranslations } from "./translations";

interface ViewModelArgs {
onSelect?: (isSelected: boolean) => void;
translations: LanguageChooserTranslations;
}

export class LanguageCardViewModel implements Selectable {
constructor(language: ILanguage, { onSelect, translations }: ViewModelArgs) {
this.language = language;

this.title = language.autonym ?? language.exonym;

if (language.autonym && language.autonym !== language.exonym) {
this.secondTitle = language.exonym;
}

if (language.regionNamesForDisplay || language.isMacrolanguage) {
this.description = language.isMacrolanguage
? language.regionNamesForDisplay
? translations.macrolanguageOfRegionLabel(
language.regionNamesForDisplay
)
: translations.macrolanguageLabel
: translations.languageOfRegionLabel(language.regionNamesForDisplay);
}

this.isSelected = new Field(false, (isSelected) => {
if (onSelect) {
onSelect(isSelected);
}
});
}

readonly language: ILanguage;

// Display data
readonly title: string;
readonly secondTitle?: string;
readonly description?: string;

readonly isSelected: Field<boolean>;
}
Loading
Loading