diff --git a/README.md b/README.md index 999a2c3..0d9751e 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,44 @@ -# sv +# Character Records Generator -Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli). +A web-based character records tool for [Aurora Station](https://aurorastation.org/). Hosted at [c.ily.rs](https://c.ily.rs). -## Creating a project +Pick a template and fill in the form. Each section covers a different record. Blank fields are omitted from the output automatically, so no rush to finish everything. -If you're seeing this, you've probably already done this step. Congrats! - -```sh -# create a new project -npx sv create my-app -``` - -To recreate this project with the same configuration: - -```sh -# recreate this project -npx sv@0.12.8 create --template minimal --types ts --no-install . -``` - -## Developing - -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: +Characters save to your browser. You can also export to a file or generate a share link: the link itself encodes the full set of records, so functionally it's a save file. + +Share links let the recipient see a preview of your records, with the option to import the character into their own roster. + +This tool is entirely data-driven in XML, and it's already set up for template sharing. A visual template editor is coming soon, so anybody can create their own templates and share them between one another. + +For issues, your best chance of getting a reply is to make an issue here, or to ping @llywelwyn in Discord. + +Cheers. + +## Development ```sh +npm install npm run dev - -# or start the server and open the app in a new browser tab -npm run dev -- --open ``` -## Building - -To create a production version of your app: +Build for production: ```sh npm run build ``` -You can preview the production build with `npm run preview`. +Validate the data files: -> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment. +```sh +npm run validate +``` + +Run tests: + +```sh +npx vitest run +``` + +## Where did the old WPF app go? + +This used to be a WPF desktop app. The last version of that lives at [`03feee5`](https://github.com/Aurorastation/character-records-generator/tree/03feee572bc7085fd8f9c458490a5dcc642ce689). diff --git a/data/templates/standard.xml b/data/templates/standard.xml index 077a101..1f9dd9b 100644 --- a/data/templates/standard.xml +++ b/data/templates/standard.xml @@ -38,8 +38,7 @@ The following information is protected by doctor-patient confidentiality laws. Do not release without patient's consent. - diff --git a/package-lock.json b/package-lock.json index 14db5e2..2f2fdfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,7 @@ "zod": "^4.3.6" }, "devDependencies": { - "@sveltejs/adapter-auto": "^7.0.0", - "@sveltejs/adapter-static": "^3.0.10", + "@sveltejs/adapter-auto": "^7.0.1", "@sveltejs/kit": "^2.50.2", "@sveltejs/vite-plugin-svelte": "^6.2.4", "@tailwindcss/vite": "^4.2.2", @@ -1112,16 +1111,6 @@ "@sveltejs/kit": "^2.0.0" } }, - "node_modules/@sveltejs/adapter-static": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.10.tgz", - "integrity": "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@sveltejs/kit": "^2.0.0" - } - }, "node_modules/@sveltejs/kit": { "version": "2.55.0", "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.55.0.tgz", diff --git a/package.json b/package.json index d7123e1..542a588 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "validate": "scripts/validate-xml.sh" }, "devDependencies": { - "@sveltejs/adapter-auto": "^7.0.0", - "@sveltejs/adapter-static": "^3.0.10", + "@sveltejs/adapter-auto": "^7.0.1", "@sveltejs/kit": "^2.50.2", "@sveltejs/vite-plugin-svelte": "^6.2.4", "@tailwindcss/vite": "^4.2.2", diff --git a/src/app.css b/src/app.css index 1909965..ae171d5 100644 --- a/src/app.css +++ b/src/app.css @@ -17,6 +17,7 @@ --text-muted: #737373; --accent: #0066cc; --accent-hover: #0052a3; + --error: #dc2626; } .dark { @@ -28,6 +29,7 @@ --text-muted: #a3a3a3; --accent: #4da6ff; --accent-hover: #80bfff; + --error: #f87171; } body { @@ -35,3 +37,9 @@ body { color: var(--text); font-family: system-ui, -apple-system, sans-serif; } + +.field-error input, +.field-error select, +.field-error textarea { + border-color: var(--error) !important; +} diff --git a/src/app.html b/src/app.html index a047305..2a6e487 100644 --- a/src/app.html +++ b/src/app.html @@ -3,7 +3,7 @@ - Aurora Records + Character Records %sveltekit.head% diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte index a922ccb..912b59f 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -1,5 +1,5 @@ @@ -55,12 +62,26 @@ {#if expanded}
{#each record.fields as field} - onFieldChange(slugify(field.label), v)} - /> + {@const key = slugify(field.label)} + {@const hasError = isRequired(field) && touched[key] && isFieldEmpty(data[key])} +
{ + if (isRequired(field) && !(e.currentTarget as HTMLElement).contains(e.relatedTarget as Node)) { + touched[key] = true; + } + }} + > + onFieldChange(key, v)} + /> + {#if hasError} +

This field is required

+ {/if} +
{/each}
{/if} diff --git a/src/lib/components/ShareMenu.svelte b/src/lib/components/ShareMenu.svelte index 2b03bd6..2da40a2 100644 --- a/src/lib/components/ShareMenu.svelte +++ b/src/lib/components/ShareMenu.svelte @@ -36,12 +36,12 @@ + + {/if} + {#if fileImportData}
@@ -109,19 +129,40 @@ {/if} {:else} -
-

No characters yet.

- +
+
+ + +
+ + +
+
+ + + {#if showPicker} { showPicker = false; }} /> {/if} diff --git a/svelte.config.js b/svelte.config.js index 0b663ed..301e785 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,11 +1,9 @@ -import adapter from '@sveltejs/adapter-static'; +import adapter from '@sveltejs/adapter-auto'; /** @type {import('@sveltejs/kit').Config} */ const config = { kit: { - adapter: adapter({ - fallback: 'index.html' - }) + adapter: adapter() } };