import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-q0svBKW3.mjs'; import { P as PublicJob } from './jobs-CfrxlDMU.mjs'; /** * Wire enum for `salaryTimeframe`. Defined here (not re-exported from any * private catalog) so the published `@cavuno/board/format` types * stay self-contained. */ type SalaryTimeframeValue = 'per_year' | 'per_month' | 'per_week' | 'per_day' | 'per_hour'; type SalaryTimeframeInput = SalaryTimeframeValue | string | null | undefined; /** * Which ICU currency form to render. * * `'symbol'` (default) is the UNAMBIGUOUS form — `CA$`, `A$`, `CN¥` — and is * the right default for a board listing several currencies side by side. * `'narrowSymbol'` is the short form (`$`, `¥`); on a single-currency board * there is nothing to confuse it with, and it reads cleaner. A caller-supplied * presentation preference, passed straight to `Intl` — not a word. */ type CurrencyDisplay = 'symbol' | 'narrowSymbol'; /** * Number notation preference, passed straight to `Intl.NumberFormat`. * * When omitted, magnitude picks: `'compact'` only where ICU actually * shortens (absolute value ≥ 1000 → `$90K`); smaller values stay * `'standard'` so hourly/day rates keep CLDR minor units (`$22.50`, * `KWD 22.567`). Compact on a two-figure rate is meaningless and drops * cents. Caller override always wins. */ type NumberNotation = 'compact' | 'standard'; /** * Formatted salary amount + which open/closed bound it represents. * Applications own: * - chrome words for `from` / `upTo` (e.g. "From", "ab") * - joining `text` with `timeframe` (order, spacing, `/`, particles) * - bidi isolation around each operand when directions may differ * (U+2066/U+2069 FSI/PDI, or HTML `` / `dir="auto"`) */ type FormattedSalaryRange = { /** Intl-formatted amount (or range). No timeframe attached. */ text: string; /** * The wire timeframe enum, passed straight back — NOT a word. * * Every rendering of it is presentation: "year", "Yearly", "/yr", * "per annum", "pro Jahr", "年収". `Intl` can produce exactly one of * those forms, so producing it here would pick for the application. * The app maps the enum through its own catalog, the same way it maps * `bound` and breadcrumb `kind`. * * `null` when the wire value is absent or not a known timeframe. */ timeframe: SalaryTimeframeValue | null; bound: 'range' | 'from' | 'upTo'; }; /** * Format a per-job salary range in the BOARD language * (`board.context().language` — required, never defaulted; see ). * * Returns `{ text, timeframe, bound }` so applications can: * - attach open-range chrome in their own locale (`bound`) * - compose amount + timeframe order themselves (prefix vs postfix, with or * without `/`, with or without a space — ja/zh often glue with no space) * - isolate bidi when composing (see module JSDoc) * * Returns `null` when both bounds are null, currency is missing/empty, the * locale is invalid/unsupported, or `Intl` rejects the currency format. * * @example * formatSalaryRange('en', 90000, 120000, 'per_year', 'USD'); * // { text: "$90–120K", timeframe: "per_year", bound: "range" } * formatSalaryRange('en', 90000, null, 'per_year', 'USD'); * // { text: "$90K", timeframe: "per_year", bound: "from" } * formatSalaryRange('de', 90000, 120000, 'per_year', 'EUR'); * // { text: "90.000–120.000 €", timeframe: "per_year", bound: "range" } * formatSalaryRange('de', 90000, 120000, 'per_year', null); * // null // no currency → no salary * formatSalaryRange('en', 22.5, null, 'per_hour', 'USD'); * // { text: "$22.50", timeframe: "per_hour", bound: "from" } // magnitude → standard */ declare function formatSalaryRange(language: string, min: number | null, max: number | null, timeframe: SalaryTimeframeInput, currency?: string | null, currencyDisplay?: CurrencyDisplay, notation?: NumberNotation): FormattedSalaryRange | null; /** * Google for Jobs `JobPosting` structured data on the `@cavuno/board` wire * types, transcribed field-by-field from the hosted board's generator * (the hosted board implementation + `job-posting-location-json-ld.ts`) and * tested against the hosted behavior. * * JSON-LD structure is locale-neutral per schema.org — no board-language * parameter here; the only display strings are wire values passed through. * * Named exclusions (hosted behaviours with no wire twin, recorded in the * public API contract): * - `board.companyWebsiteUrl` — hosted falls back to it for `sameAs` when * the company has no website; not on the wire. * - the hosted `job.place`/`locationLabel` jobLocation fallback (used when * a job has no office locations) — the wire `PublicJob` carries no * resolved place geo, only `officeLocations`. */ type JsonLdObject = Record; /** The only board fields JSON-LD needs — keeps callers' shapes flexible. */ type JsonLdBoard = Pick & { /** * The operating company's registered name, used as the organization name * for a job with no company of its own — ahead of the board's display * name, matching the hosted board. * * Read from `contact.legalName`, which is where `board.context()` puts it, * so passing the context object straight through (the documented call * shape) just works. `legalName` at the top level is accepted too, for * callers that flatten the board into their own view model. */ contact?: { legalName?: string | null; } | null; legalName?: string | null; }; /** * Worldwide-remote jobs must still emit `applicantLocationRequirements` * next to TELECOMMUTE (Google requires a location signal), so the hosted * board — and this transcription — lists every country it recognises. * * This is the hosted board's exact country catalog: sorted by English common * name, includes `XK` (Kosovo), and excludes `KP` (North Korea). tested * against the hosted list so the two cannot drift. */ declare const ALL_COUNTRY_CODES: readonly ["AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BA", "BW", "BV", "BR", "IO", "VG", "BN", "BG", "BF", "BI", "KH", "CM", "CA", "CV", "BQ", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CK", "CR", "HR", "CU", "CW", "CY", "CZ", "DK", "DJ", "DM", "DO", "CD", "EC", "EG", "SV", "GQ", "ER", "EE", "SZ", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IQ", "IE", "IM", "IL", "IT", "CI", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "XK", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MK", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "CG", "RE", "RO", "RU", "RW", "BL", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "RS", "SC", "SL", "SG", "SX", "SK", "SI", "SB", "SO", "ZA", "GS", "KR", "SS", "ES", "LK", "SD", "SR", "SJ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "US", "UM", "VI", "UY", "UZ", "VU", "VA", "VE", "VN", "WF", "EH", "YE", "ZM", "ZW"]; /** * Build the Google for Jobs `JobPosting` JSON-LD object for a job detail * page, or `null` when nothing renderable remains after pruning. Embed the * result in a `