import { type ReactNode } from "react"; import { type DatePickerLabels } from "./date_picker"; import { type CalendarLabels } from "./date_calendar"; import { type CalendarViewLabels } from "./calendar/types"; import { type GanttLabels } from "./gantt/types"; import { type SocialPostPreviewLabels } from "./social_post_rules"; import { type PaginationLabels } from "./pagination"; import { type SortHeaderLabels } from "./sort_header"; import { type EntryGridLabels } from "./entry_grid"; import { type StateMatrixLabels } from "./state_matrix"; import { type TimetableLabels } from "./timetable"; import { type ConfidenceCalloutLabels } from "./confidence_callout"; import { type ProgressRemainingLabels } from "./progress"; import { type DateFilterFieldLabels } from "./date_filter"; import type { GalleryLabels } from "./file_preview"; import type { FilesEditorLabels } from "./files_editor"; import { type FindingLabels } from "./finding"; import { type AgeingLabels, type DeadlineLabels } from "./deadline"; import { type MemberProfileLabels } from "./member_profile_card"; import { type ShapeLabels } from "./shape_frame"; /** * The kit's localizable strings, one slice per string-bearing component. A * `LoticsLocale` is plain DATA — it carries no i18n LOGIC, so the kit stays * translation-agnostic while an app supplies the pack once at its root. Each * slice REUSES the component's own `*Labels` type, so a missing translation is * a compile error here, never a silent English leak at a call site. * * Resolution order in every wired component: an explicit per-instance prop * wins, else this locale (from `LoticsLocaleProvider`, default `en`). */ export interface LoticsLocale { /** The BCP-47 language tag this pack renders in (`en` → `"en-US"`). It drives * every `Intl`-derived rendering the kit does — the segmented date field's * part ORDER and 12/24h, the calendar's names, `formatDate` display — without * the author threading a `locale` prop, which still overrides it. */ bcp47: string; pagination: Required; sortHeader: Required; timetable: Required; stateMatrix: Required; /** `EntryGrid`: what a listener is told a pair with no entry holds — nothing * was DUE there, which is a different fact from a zero. */ entryGrid: Required & { notDue: string; }; /** `Worksheet`: the two words no field can name — `margin` is ARITHMETIC over * the two bases beside it, and `view` is a reading of the sheet. */ worksheet: { margin: string; view: string; internal: string; customer: string; }; referenceField: { open: string; change: string; clear: string; edit: string; save: string; saving: string; cancel: string; }; optionList: { selectAll: string; deselectAll: string; noResults: string; recent: string; searchPlaceholder: string; someSelected: string; }; /** `Select`'s empty option, when the caller declares empty a CHOICE * (`clearable`). A value, not an action — hence "None" rather than "Clear". */ picker: { emptyOption: string; }; datePicker: DatePickerLabels; calendar: CalendarLabels; /** `CalendarView` and its parts — the SCHEDULING surface. Distinct from * `calendar` above, which is the date PICKER's month grid. */ calendarView: CalendarViewLabels; gantt: GanttLabels; socialPostPreview: SocialPostPreviewLabels; filterChip: { clear: string; }; filterBand: { filters: string; clearAll: string; done: string; }; floatingActionBar: { clear: string; }; /** `FormField`: the marker beside the label — the form marks one side or the * other (`FormMarksContext`), never both, so both words live here. */ formField: { optional: string; required: string; }; dangerSection: { title: string; }; /** `Alert.confirm`'s CHROME. Everything said ABOUT the object (the question, * the commit's verb and noun) is the CALLER's. */ confirm: { cancel: string; /** The consequence a request that states none falls back to. */ irreversible: string; /** A commit the host refused with no message of its own. */ failed: string; /** The typed gate's instruction, and the field's accessible name. */ typedPrompt: (name: string) => string; }; drawer: { previous: string; next: string; close: string; }; shape: ShapeLabels; /** HOW THE ROWS ARE ARRANGED — one name per geometry the same register can be * drawn in. The names are the KIT's, so a reader meets the same eight words in * every app. */ layout: { name: string; table: string; list: string; cards: string; gallery: string; board: string; calendar: string; timeline: string; gantt: string; }; /** THE ONE SUBJECT AN APP IS READ INSIDE — `ScopeSwitcher`'s band. Nothing is * read until a subject is, so a register that would list rows names what to * pick instead. */ scope: { pick: (entity: string) => string; }; /** WHOSE MOVE IT IS — `Awaiting`'s own sentence, which names the obligor and * leaves the clock beside it to the `deadline` vocabulary. */ awaiting: { with: (party: string) => string; unnamed: string; }; /** A CORRESPONDENCE'S OWN WORDS — which reply ANSWERS the question, and what the * box at the foot invites. A discussion's own chrome is `CommentThreadLabels`. */ thread: { answer: string; mark: (author: string) => string; reply: string; }; /** THE ROWS IN VIEW, SAVED — the register's own export act, and the line it * wears where the app ships without the writer that makes the sheet. */ saved: { label: string; unavailable: string; }; /** THE PANEL AN ACT OPENS WHERE THE READER ANSWERS SOMETHING FIRST — the line * naming what the press is over. The VERB is the act's own label. */ act: { over: (count: number) => string; }; /** ROWS IN, FROM A FILE — the register's import act and the chrome of the run * it opens: the three steps, what each row's verdict says, and what landed. */ intake: { unavailable: string; steps: { file: string; columns: string; preview: string; }; hint: string; unreadable: string; empty: string; /** The key column nothing reached — a run with no key is a run that cannot be safe twice. */ keyOwed: (label: string) => string; ready: (count: number) => string; refused: (count: number) => string; verdict: string; commit: string; back: string; landed: (created: number, updated: number) => string; reasons: { blank: (label: string) => string; number: (label: string, said: string) => string; date: (label: string, said: string) => string; option: (label: string, said: string) => string; }; }; record: RecordLabels; inline: { saveError: string; save: string; cancel: string; }; /** `ChoiceList` custom-answer placeholder + `ClarifyWizard` navigation chrome. */ clarify: { otherPlaceholder: string; back: string; next: string; cancel: string; submit: string; }; /** `GuidedRun`'s own chrome — the two ways through the run, the clock over the * sequence, and the door onto a step's record. */ guidedRun: { back: string; next: string; steps: string; /** How long this reader has been in the run. The pack decides whether the hours * are spelled at all, because a run under an hour reads wrong as "0 h 24 min". */ elapsed: (hours: number, minutes: number) => string; /** Every step is answered and the run is past its last one. */ complete: string; open: string; }; chargeLines: { total: string; quantity: (label: string) => string; unitPrice: (label: string) => string; amount: (label: string) => string; }; ledger: { rowDetails: (label: string) => string; }; /** `SectionNav`: the bar's fallback name when `activeKey` matches no item, and * what the attention dot ANNOUNCES — a bare mark names nothing. */ sectionNav: { sections: string; needsAttention: string; hasProblem: string; }; /** `RunningLedger`'s closing line — the ledger's one derived, always-current * figure. */ runningLedger: { currentBalance: string; }; /** `Step`/`ChecklistItem`'s toggleable MARKER, where the caller names none. */ stepper: { complete: string; progress: string; }; /** `ActivityIndicator`: what the ring announces INSTEAD of a figure — a * `progressbar` with no value has none. */ activityIndicator: { running: string; }; /** `ChecklistGroup`'s disclosure — the text that shows or hides a phase's rows. */ checklist: { expand: string; collapse: string; }; /** `TextDisclosure` supplies the VERB, and builds the whole phrase because word * order is not shared: English puts the verb first. */ textDisclosure: { show: (label: string) => string; hide: (label: string) => string; }; /** The info-popover trigger's screen-reader name on a heading. */ sectionHeading: { info: string; }; regionState: { retry: string; }; chip: { remove: string; }; /** `ReorderItem`'s controls. Each name says WHICH row it moves, because ten * identical "move up" buttons are one control to a screen reader. */ reorderItem: { moveUp: (label: string | undefined) => string; moveDown: (label: string | undefined) => string; remove: (label: string | undefined) => string; }; /** `Itinerary`: the verb that adds a stop to one day, named by its day for a * screen reader, and the mark a stay leaves on the days it runs through. */ itinerary: { add: string; addOn: (day: string) => string; continues: string; }; board: { open: (title: string) => string; move: (title: string) => string; moveTo: (column: string) => string; empty: string; }; trend: { up: string; down: string; }; breakdown: { more: (hidden: number) => string; less: string; }; /** `ComparisonBar`: the SHARE and its direction, and nothing about the domain — * whether cheaper is good news is the caller's to say, through `deltaLabel`. */ comparisonBar: { lower: (percent: string) => string; higher: (percent: string) => string; same: string; }; /** The countdown vocabulary — see `deadline.ts`. 0 and 1 get their own words * because "0 days left" reads as broken exactly when it matters most. */ deadline: DeadlineLabels; /** What an amount's AGE is called, band by band — see `ageingBands`. */ ageing: AgeingLabels; confidence: ConfidenceCalloutLabels; /** `Progress` under `reading="remaining"`. */ progress: Required; finding: FindingLabels; /** `DiffMark`'s accessible word per mark — meaning may never rest on colour. */ diff: { added: string; changed: string; removed: string; unchanged: string; }; dateRange: DateFilterFieldLabels; gallery: GalleryLabels; /** `MediaPlayer`: the caption when a source will not load. Agnostic on purpose: * the kit does not know whether it is a recording, a clip or an attachment. */ mediaPlayer: { loadFailed: string; }; /** `Avatar`'s fallback name, where there is no `name`. `MemberChip` resolves the * same blank through it. */ avatar: { unknown: string; more: (count: number) => string; }; memberProfile: Required; /** `BackButton` + `PopoverNavHeader`: the back-chevron's a11y name. */ nav: { back: string; }; chart: { noData: string; total: string; }; composer: { send: string; stop: string; }; /** `Dialog` / `Drawer` / `Popover`: the dismiss control's a11y / tooltip name. */ overlay: { close: string; }; /** `ToastProvider`: the viewport region and the three tone marks — the mark is * the only thing carrying the valence, and a colour names nothing. */ toast: { notifications: string; success: string; error: string; warning: string; undo: string; }; /** `FileDropzone`. `hint` is a generic default apps override with an * accepted-types line. */ fileDropzone: { label: string; hint: string; drop: string; }; columnMap: { ignore: string; suggested: string; unreached: (names: string[]) => string; }; fileThumbnail: { remove: string; }; markdownToolbar: { /** The band's own accessible name — a `role="toolbar"` is name-required. */ label: string; linkUrl: string; heading1: string; heading2: string; heading3: string; bold: string; italic: string; inlineCode: string; bulletList: string; numberedList: string; quote: string; codeBlock: string; link: string; insertTable: string; divider: string; }; filesEditor: FilesEditorLabels; /** `FileThumbnailGrid`'s in-flight tiles. The plain `uploading` state has no * entry on purpose — only a state that wants ATTENTION earns one. */ fileUpload: { paused: string; retrying: string; failed: string; /** Retry is futile on the same input — a dead picker ref, or zero bytes. */ unavailable: string; retry: string; retryAll: string; }; /** `ImageGallery`. `loading` names the SPINNER alone in the frame before the * first picture — an indeterminate `progressbar` is name-required. */ imageGallery: { empty: string; loading: string; rotateLeft: string; rotateRight: string; zoom: string; }; /** `InfoPopover`'s ⓘ trigger. `about` names the SUBJECT, which is what a reader * needs when a page carries several. */ infoPopover: { more: string; about: (label: string) => string; }; /** `FileRow` / `Sources`: two slices, because a pack may open a FILE and open a * SOURCE with different words. `add` is the PLACEHOLDER row's verb: a slot with * nothing filed in it cannot be opened. */ fileRow: { open: (name: string) => string; add: (name: string) => string; }; sources: { open: (label: string) => string; heading: string; }; /** `NumberInput stepper`'s two discs, named for the value they move. */ numberInput: { decrease: (label: string | undefined) => string; increase: (label: string | undefined) => string; }; /** The two bounds of a numeric range, named for what they bound. */ range: { min: (label: string) => string; max: (label: string) => string; }; matrix: { total: string; less: string; more: string; }; markdown: { copyTable: string; copied: string; }; /** The way back to a feed's newest content — `FollowScroll showJumpToLatest`. */ scrollToBottom: { tooltip: string; }; textInputField: { clear: string; }; /** `AgentRun` chrome, plus `tools` — the display label per PLATFORM tool name, * localized here so every app inherits it. A name absent from the map falls back * to its prettified form, and `labelForCall` still overrides per call. */ agentRun: { starting: string; thinking: string; thinkingStreaming: string; input: string; error: string; output: string; awaiting: string; retry: string; stop: string; tools: Record; }; /** `AgentRun variant="pill"`: what the collapsed pill says when no step names * itself. */ agentProgress: { working: string; done: string; stopped: string; }; /** `@lotics/ui-internal`'s `ApprovalPrompt` — the surface that ANSWERS * `AgentRun`'s read-only `awaiting` row. */ approvalPrompt: { message: string; approve: string; deny: string; }; /** `@lotics/ui-internal`'s `MessageActions`. */ messageActions: { /** The bar's own accessible name — a `role="toolbar"` is name-required. */ label: string; copy: string; copied: string; regenerate: string; edit: string; previousVersion: string; nextVersion: string; }; /** `CopyButton`. WHAT is being copied stays a per-instance `label`; `failed` says * the clipboard refused the write, the only thing a reader can act on. */ copyButton: { copy: string; copied: string; failed: string; }; /** `CommentsButton`'s accessible name. `withSubject` builds the WHOLE phrase, so * a pack chooses the word ORDER: the subject leads in some languages. It joins * with a WORD because a screen reader drops punctuation. */ commentsButton: { comment: string; comments: string; withSubject: (counted: string, subject: string) => string; }; } /** The words of a record surface — `RecordPage` and the sections it is made of. */ export interface RecordLabels { attention: (count: number) => string; goTo: (section: string) => string; /** An attention line for a required set — what the record still owes, BY NAME. */ gap: (names: readonly string[]) => string; /** A fact with no value. */ none: string; /** What a record's own identity field is CALLED, for the editor on the `h1`. */ name: string; /** The row of ways to REACH the subject, as a list's accessible name. */ contacts: string; /** A yes/no fact's two words — a stated "no" is not an absent value, and * `none` would read as unknown. */ yes: string; no: string; /** THE DOOR ON A LINK FACT, as a screen reader names it. It names the * DESTINATION: a record's aside carries several, and four controls announcing * "Open" are four a reader cannot tell apart. */ open: (name: string) => string; /** The door opened on an id no record has. */ missing: string; /** The kit's words for the sections a record has whatever the business is. */ files: string; comments: string; related: string; /** THE RECORD'S OWN PARTICULARS, heading the fields no other section took — the * kit's word, because the business has none. */ details: string; /** Present items outside the required set. */ extra: string; add: string; /** A filed row's ⋯ menu, as a screen reader names it. */ actions: string; remove: string; /** The confirm's question when a filed item is un-filed — a FUNCTION, because * word order is not shared between languages. */ removeItem: (name: string) => string; /** What a ghost row says where nothing CAN be added — a read-only desk. */ absent: string; /** SEVERAL OWED SLOTS CONDENSED INTO ONE — a strip too narrow to draw the gaps * apart draws one tile for the run, and the number belongs in its name. Singular * is {@link absent}. */ owed: (count: number, what: string) => string; showAll: (hidden: number) => string; /** The fact grid's fold, as the NOUN behind it — "12 more fields". * `TextDisclosure` supplies the verb. */ more: (hidden: number) => string; selected: (count: number) => string; /** A lifecycle's committing act — "Move to Confirmed". */ advance: (stage: string) => string; /** The quiet overflow beside that act, as a screen reader names it: every move * the record can make that is NOT the next stage. */ otherMoves: string; } /** The platform default — English. Every component's hardcoded default lives here, * so the strings are documented in one place and overridable. */ export declare const en: LoticsLocale; /** Vietnamese. Maintained once here so every app (and the frontend) shares one * canonical translation — no per-app drift ("Chọn tất cả" vs "Chọn hết"). */ export declare const vi: LoticsLocale; /** * The active pack, for a surface that cannot use {@link useLoticsLocale} because * it is not inside the provider's tree: the LAST provider mounted, and `en` once * every provider is gone. */ export declare function getLoticsLocale(): LoticsLocale; interface LoticsLocaleProviderProps { /** The locale pack supplying every kit string. Import a shipped pack * (`import { vi } from "@lotics/ui/locale"`) or pass your own `LoticsLocale`. */ locale: LoticsLocale; children: ReactNode; } /** * App-root provider that supplies localized strings to @lotics/ui primitives. * Wrap your top-level element once and every wired component picks up the pack. * A per-instance label prop still overrides for one-offs; without a provider the * English default applies. */ export declare function LoticsLocaleProvider(props: LoticsLocaleProviderProps): import("react").JSX.Element; /** Read the current locale. Wired primitives call this; apps use the provider. */ export declare function useLoticsLocale(): LoticsLocale; /** * Resolve the effective BCP-47 tag for a locale-aware control: an explicit * per-instance `locale` wins, else the pack's own {@link LoticsLocale.bcp47}. */ export declare function resolveLocaleTag(locale: LoticsLocale, explicit?: string): string; /** * The BCP-47 tag a date / time control should render in: the explicit `locale` * prop when given, else the active `LoticsLocaleProvider` pack's tag — so the * `vi` pack yields dd/MM/yyyy segment order and Vietnamese calendar names with * no per-instance prop. */ export declare function useLocaleTag(explicit?: string): string; /** * WHAT A PLOTTED FIGURE PRINTS — at most one fraction digit, read at a glance * against the mark beside it. A figure standing in a ROW of figures — a * breakdown's value, a matrix cell — passes nothing and keeps the locale's own * precision. */ export declare const PLOTTED_FIGURE: Intl.NumberFormatOptions; /** * A FIGURE IN THE READER'S OWN LANGUAGE — grouped by the PACK's tag, never the * browser's. A formatter built at module level cannot reach the pack, so a * Vietnamese workspace's axis printed `2,000.5` beside a register printing * `2.000,5`; it is therefore read where the pack is, inside the component. A * caller's own `formatNumber` / `formatValue` still wins. */ export declare function useNumberFormat(options?: Intl.NumberFormatOptions): (value: number) => string; export {};