diff --git a/.changeset/dark-mode-follows-system.md b/.changeset/dark-mode-follows-system.md new file mode 100644 index 0000000..249057d --- /dev/null +++ b/.changeset/dark-mode-follows-system.md @@ -0,0 +1,16 @@ +--- +'@wirecore/wirelayer-tokens': minor +'@wirecore/wirelayer-css': minor +'@wirecore/wirelayer-vue': patch +'@wirecore/wirelayer-react': patch +--- + +**Behavior change:** without `data-mode` the page now follows the system setting (`prefers-color-scheme`) instead +of always being light. `data-mode="light"` or `data-mode="dark"` forces a mode as before, also for a part of the page +(a forced light part stays light on a dark system). + +- The `dark:` variant follows the same rules, and so do the dark colors of the built-in themes and of custom themes + generated with `themeToCss`. +- Charts (Chart, ChartCanvas, Sparkline) recolor when the system setting changes. +- Apps that relied on "no attribute = light" and want to keep it: set `data-mode="light"` on ``. Apps that set + `data-mode` from `prefers-color-scheme` with JavaScript can drop that. diff --git a/.changeset/datatable-csv-separator.md b/.changeset/datatable-csv-separator.md new file mode 100644 index 0000000..8211290 --- /dev/null +++ b/.changeset/datatable-csv-separator.md @@ -0,0 +1,11 @@ +--- +'@wirecore/wirelayer-recipes': minor +'@wirecore/wirelayer-vue': minor +'@wirecore/wirelayer-react': minor +'@wirecore/wirelayer-native': minor +--- + +DataTable: new prop `csvSeparator` for the CSV export, also for the built-in export button. By default the separator +now follows the locale like a spreadsheet does (`csvSeparator(locale)` from the recipes): `;` where numbers have a +decimal comma (de-DE, fr-FR …), `,` otherwise (en-US …). Before, it was always `;`. `exportCsv({ separator })` still +wins over both. diff --git a/.changeset/datatable-feature-modules.md b/.changeset/datatable-feature-modules.md new file mode 100644 index 0000000..9faa76c --- /dev/null +++ b/.changeset/datatable-feature-modules.md @@ -0,0 +1,22 @@ +--- +'@wirecore/wirelayer-vue': minor +'@wirecore/wirelayer-react': minor +--- + +**Breaking:** DataTable feature modules. Parts of the DataTable that bring a lot of code along are imported on their own +and passed in `features` – a minimal table is about a fifth smaller (gzip), and `@tanstack/vue-virtual` or +`@tanstack/react-virtual` is only needed for virtual rows. + +- `virtual` needs the feature `virtualRows` from `/virtual`; without it all rows are rendered (with a hint in + development). +- Date and number filters and editors use the browser's inputs; the DatePicker and NumberInput come with the features + `dateInput` and `numberInput` from `/data-table`. + +```tsx +import { DataTable, dateInput, numberInput } from '@wirecore/wirelayer-react/data-table'; // or -vue +import { virtualRows } from '@wirecore/wirelayer-react/virtual'; + +const features = [virtualRows, dateInput, numberInput]; + +; +``` diff --git a/.changeset/docs-english-default.md b/.changeset/docs-english-default.md new file mode 100644 index 0000000..736de27 --- /dev/null +++ b/.changeset/docs-english-default.md @@ -0,0 +1,10 @@ +--- +'@wirecore/wirelayer-mcp': patch +'@wirecore/wirelayer-vue': patch +'@wirecore/wirelayer-react': patch +'@wirecore/wirelayer-native': patch +'@wirecore/wirelayer-recipes': patch +--- + +Documentation says English is the default language, as it is in the code: `useLocale` and the MCP server/`llms.txt` +no longer claim German without a `LocaleProvider`. diff --git a/.changeset/german-language-module.md b/.changeset/german-language-module.md new file mode 100644 index 0000000..d6263d0 --- /dev/null +++ b/.changeset/german-language-module.md @@ -0,0 +1,21 @@ +--- +'@wirecore/wirelayer-recipes': minor +'@wirecore/wirelayer-vue': minor +'@wirecore/wirelayer-react': minor +'@wirecore/wirelayer-native': minor +--- + +**Breaking:** German is a language module like French or Spanish and no longer part of the default bundle (about half +of the built-in texts). Only English is built in. Apps that use German register it once at startup, before the first +render: + +```ts +import { registerLocale } from '@wirecore/wirelayer-vue'; // or -react, -native +import { de } from '@wirecore/wirelayer-vue/locales/de'; + +registerLocale('de', de); +``` + +`messages` only contains `en` now; the German texts are `de` from `…/locales/de`. The German names and search words of +the EmojiPicker moved there as well (`emojiPicker.emojis`); the built-in emojis are English. `localeEmojis(texts)` no +longer takes a locale – pass the lines of the language module (`localeEmojis(de.emojiPicker.emojis)`). diff --git a/.changeset/reexport-recipe-types.md b/.changeset/reexport-recipe-types.md new file mode 100644 index 0000000..d7c8735 --- /dev/null +++ b/.changeset/reexport-recipe-types.md @@ -0,0 +1,10 @@ +--- +'@wirecore/wirelayer-vue': minor +'@wirecore/wirelayer-react': minor +'@wirecore/wirelayer-native': minor +--- + +The types that appear in the props are exported by the component packages themselves, so apps no longer need +`@wirecore/wirelayer-recipes` (or `NonNullable`) for them – e.g. `BadgeVariant`, +`ButtonVariant`, `ButtonSize`, `AlertStatus`, `DialogPosition`, `OverlaySize`, `StatusDotStatus`, `DataSource`, +`RecipeClasses`. `/data-table` adds `PivotValue`, `/virtual` `ItemAccessor`, React Native's `/pdf` `PdfZoom`. diff --git a/.changeset/vue-bind-input-types.md b/.changeset/vue-bind-input-types.md new file mode 100644 index 0000000..2d243b7 --- /dev/null +++ b/.changeset/vue-bind-input-types.md @@ -0,0 +1,7 @@ +--- +'@wirecore/wirelayer-vue': patch +--- + +`bindInput` from `/form` fits `Input` and `Textarea` in compiled SFC templates: `onUpdate:modelValue` accepts +`string | undefined` (what the components emit) and `modelValue` falls back to `''`, like the React variant. Before, +`` was a vue-tsc error. diff --git a/README.md b/README.md index 6438113..0a23cff 100644 --- a/README.md +++ b/README.md @@ -73,36 +73,38 @@ All components and props: Storybook and `llms.txt`, or the MCP server `@wirecore What a large library needs lives in its own subpaths – it only ends up in the bundle when the app imports it, and then needs the respective peer dependency: -| Subpath | Vue / React | React Native (`@wirecore/wirelayer-native/…`) | -| ----------------- | --------------------------------------- | ---------------------------------------------------- | -| `/form` | TanStack Form, validators, FormList | TanStack Form | -| `/data-table` | DataTable (TanStack Table + Virtual) | DataTable without TanStack (table or cards) | -| `/virtual` | VirtualSelect, VirtualList, VirtualTree | – | -| `/chart` | Charts on Chart.js | Charts on react-native-svg | -| `/editor` | Rich text editor on Tiptap | – | -| `/code` | CodeHighlight on Shiki (`shiki/core`) | CodeHighlight on Shiki (JavaScript RegExp engine) | -| `/pdf` | PdfViewer on pdf.js (`pdfjs-dist`) | PdfViewer on react-native-pdf (development build) | -| `/locales/` | Language modules (see below) | Language modules | -| `/expo-*` | – | `expo-sharing`, `expo-clipboard`, file/image pickers | +| Subpath | Vue / React | React Native (`@wirecore/wirelayer-native/…`) | +| ----------------- | ------------------------------------------------------------------ | ---------------------------------------------------- | +| `/form` | TanStack Form, validators, FormList | TanStack Form | +| `/data-table` | DataTable (TanStack Table) | DataTable without TanStack (table or cards) | +| `/virtual` | VirtualSelect, VirtualList, VirtualTree, `virtualRows` (DataTable) | – | +| `/chart` | Charts on Chart.js | Charts on react-native-svg | +| `/editor` | Rich text editor on Tiptap | – | +| `/code` | CodeHighlight on Shiki (`shiki/core`) | CodeHighlight on Shiki (JavaScript RegExp engine) | +| `/pdf` | PdfViewer on pdf.js (`pdfjs-dist`) | PdfViewer on react-native-pdf (development build) | +| `/locales/` | Language modules (see below) | Language modules | +| `/expo-*` | – | `expo-sharing`, `expo-clipboard`, file/image pickers | ## Languages -English (default) and German are built in. More languages are available as separate modules and only end up in the -bundle when an app imports them: `fr`, `es`, `it`, `pt` (Portugal), `pt-BR`, `nl`, `pl`, `cs`, `hu`, `lv`, `ar` and +English (default) is built in. More languages are available as separate modules and only end up in the bundle when an +app imports them: `de`, `fr`, `es`, `it`, `pt` (Portugal), `pt-BR`, `nl`, `pl`, `cs`, `hu`, `lv`, `ar` and `tr` – each under `@wirecore/wirelayer-vue/locales/`, `@wirecore/wirelayer-react/locales/`, `@wirecore/wirelayer-native/locales/` (or `@wirecore/wirelayer-recipes/locales/`). ```ts import { registerLocale } from '@wirecore/wirelayer-vue'; // or @wirecore/wirelayer-react, @wirecore/wirelayer-native +import { de } from '@wirecore/wirelayer-vue/locales/de'; import { fr } from '@wirecore/wirelayer-vue/locales/fr'; import { ptBR } from '@wirecore/wirelayer-vue/locales/pt-BR'; // Once at startup, before the first render +registerLocale('de', de); // applies to de-DE, de-AT, de-CH … registerLocale('fr', fr); // applies to fr-FR, fr-CA, fr-CH … registerLocale('pt-BR', ptBR); // a region takes precedence over its language ``` -After that, `` is enough (`` for the built-in German). +After that, `` or `` is enough. Alternatively, `LocaleProvider` receives the texts directly (`translations={fr}`). Unregistered languages fall back to English; the writing direction (`ar`, `he`, `fa`, `ur` → right to left) follows from the locale. Custom languages are a complete `Translations` object – the TypeScript type reports missing texts. The bundled translations should be reviewed diff --git a/apps/next/app/shell.tsx b/apps/next/app/shell.tsx index 432cbf5..72cd814 100644 --- a/apps/next/app/shell.tsx +++ b/apps/next/app/shell.tsx @@ -5,17 +5,22 @@ import { AppShell, ConfirmDialog, LocaleProvider, + registerLocale, SegmentedControl, SegmentedControlItem, SidebarNav, Toaster, } from '@wirecore/wirelayer-react'; +import { de } from '@wirecore/wirelayer-react/locales/de'; import { Gauge, Send } from 'lucide-react'; import Link from 'next/link'; import { usePathname, useRouter } from 'next/navigation'; import { createContext, useContext, useState, type ReactNode } from 'react'; import { isDemoLocale, texts, type DemoLocale } from './texts'; +// German is a separate language module – registered once, before the first render (server and browser) +registerLocale('de', de); + const TextsContext = createContext(texts['en-US']); /** Texts of the page in the chosen language */ diff --git a/apps/nuxt/app/plugins/locale.ts b/apps/nuxt/app/plugins/locale.ts new file mode 100644 index 0000000..e26ef00 --- /dev/null +++ b/apps/nuxt/app/plugins/locale.ts @@ -0,0 +1,8 @@ +import { registerLocale } from '@wirecore/wirelayer-vue'; +import { de } from '@wirecore/wirelayer-vue/locales/de'; +import { defineNuxtPlugin } from '#imports'; + +// German is a separate language module – registered once, before the first render (server and browser) +export default defineNuxtPlugin(() => { + registerLocale('de', de); +}); diff --git a/apps/storybook/shared/locale.ts b/apps/storybook/shared/locale.ts index e088cc4..304e7b4 100644 --- a/apps/storybook/shared/locale.ts +++ b/apps/storybook/shared/locale.ts @@ -10,8 +10,8 @@ export const localeGlobalTypes = { icon: 'globe', items: [ { value: 'en-US', title: 'English' }, - { value: 'de-DE', title: 'Deutsch' }, // Not built in – each preview registers them (registerLocale) from its package's locales/ + { value: 'de-DE', title: 'Deutsch' }, { value: 'fr-FR', title: 'Français' }, { value: 'es-ES', title: 'Español' }, { value: 'it-IT', title: 'Italiano' }, diff --git a/apps/storybook/src/Accessibility.mdx b/apps/storybook/src/Accessibility.mdx index 6958d0c..5f87310 100644 --- a/apps/storybook/src/Accessibility.mdx +++ b/apps/storybook/src/Accessibility.mdx @@ -44,7 +44,7 @@ and all of it is checked on every test run. - Render clickable cards with `asChild` as `` or `