@nxgt/material-core 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{index-8gf9e2d4.js → index-fp0822sa.js} +3 -3
- package/dist/chunks/{index-8gf9e2d4.js.map → index-fp0822sa.js.map} +3 -3
- package/dist/chunks/index-w3ajz57t.js.map +2 -2
- package/dist/index.js +1 -1
- package/dist/lib/print-format.utils.d.ts.map +1 -1
- package/dist/pdf/index.js +1 -1
- package/dist/pdf/model/index.js +1 -1
- package/docs/roadmap.md +10 -6
- package/package.json +1 -6
|
@@ -51,7 +51,7 @@ function definePdfDocument2(build) {
|
|
|
51
51
|
function dataTable2(columns, rows, options = {}) {
|
|
52
52
|
const { currency, totalLabel, ...layout } = options;
|
|
53
53
|
const table = resolvePrintTable2(columns, rows, { currency, totalLabel });
|
|
54
|
-
const labelTotals = totalLabel === undefined &&
|
|
54
|
+
const labelTotals = totalLabel === undefined && columns[0] !== undefined && !columns[0].total;
|
|
55
55
|
const footer = labelTotals ? table.footer.map(([, ...rest]) => [null, ...rest]) : table.footer;
|
|
56
56
|
return {
|
|
57
57
|
type: "table",
|
|
@@ -72,5 +72,5 @@ function keyValueOf2(fields, data, options = {}) {
|
|
|
72
72
|
|
|
73
73
|
export { text2, heading2, stack2, row2, section2, image2, link2, spacer2, divider2, pageBreak2, table2, keyValue2, totals2, metric2, badge2, header2, pageNumber2, page2, pdfDocument2, definePdfDocument2, dataTable2, keyValueOf2 };
|
|
74
74
|
|
|
75
|
-
//# debugId=
|
|
76
|
-
//# sourceMappingURL=index-
|
|
75
|
+
//# debugId=0A73B8345AA198A764756E2164756E21
|
|
76
|
+
//# sourceMappingURL=index-fp0822sa.js.map
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"sources": ["../src/pdf/model/builders.ts", "../src/pdf/model/data-table.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"/**\n * Plain functions that return model nodes, so a document reads as code\n * rather than as nested object literals. Each returns data only.\n */\nimport type {\n\tPdfDocument,\n\tPdfInline,\n\tPdfNode,\n\tPdfPage,\n\tPrintValue,\n} from './types';\n\ntype NodeOf<T extends PdfNode['type']> = Extract<PdfNode, { type: T }>;\ntype Options<T extends PdfNode['type'], K extends string = never> = Omit<\n\tNodeOf<T>,\n\t'type' | K\n>;\n\nexport const text = (\n\tcontent: string | PdfInline[],\n\toptions: Omit<Options<'text'>, 'content'> = {},\n): NodeOf<'text'> => ({ type: 'text', content, ...options });\n\nexport const heading = (text: string, level?: 1 | 2 | 3): NodeOf<'heading'> =>\n\tlevel ? { type: 'heading', text, level } : { type: 'heading', text };\n\nexport const stack = (\n\tchildren: PdfNode[],\n\toptions: Omit<Options<'stack'>, 'children'> = {},\n): NodeOf<'stack'> => ({ type: 'stack', children, ...options });\n\nexport const row = (\n\tchildren: PdfNode[],\n\toptions: Omit<Options<'row'>, 'children'> = {},\n): NodeOf<'row'> => ({ type: 'row', children, ...options });\n\nexport const section = (\n\ttitle: string,\n\tchildren: PdfNode[],\n): NodeOf<'section'> => ({ type: 'section', title, children });\n\nexport const image = (\n\tsrc: string,\n\toptions: Omit<Options<'image'>, 'src'> = {},\n): NodeOf<'image'> => ({ type: 'image', src, ...options });\n\nexport const link = (href: string, text: string): NodeOf<'link'> => ({\n\ttype: 'link',\n\thref,\n\ttext,\n});\n\nexport const spacer = (size: number): NodeOf<'spacer'> => ({\n\ttype: 'spacer',\n\tsize,\n});\n\nexport const divider = (): NodeOf<'divider'> => ({ type: 'divider' });\n\nexport const pageBreak = (): NodeOf<'pageBreak'> => ({ type: 'pageBreak' });\n\nexport const table = (options: Options<'table'>): NodeOf<'table'> => ({\n\ttype: 'table',\n\t...options,\n});\n\nexport const keyValue = (\n\titems: { label: string; value: PrintValue }[],\n\toptions: Omit<Options<'keyValue'>, 'items'> = {},\n): NodeOf<'keyValue'> => ({ type: 'keyValue', items, ...options });\n\nexport const totals = (rows: NodeOf<'totals'>['rows']): NodeOf<'totals'> => ({\n\ttype: 'totals',\n\trows,\n});\n\nexport const metric = (options: Options<'metric'>): NodeOf<'metric'> => ({\n\ttype: 'metric',\n\t...options,\n});\n\nexport const badge = (text: string, color?: string): NodeOf<'badge'> =>\n\tcolor ? { type: 'badge', text, color } : { type: 'badge', text };\n\nexport const header = (options: Options<'header'>): NodeOf<'header'> => ({\n\ttype: 'header',\n\t...options,\n});\n\nexport const pageNumber = (\n\toptions: Options<'pageNumber'> = {},\n): NodeOf<'pageNumber'> => ({ type: 'pageNumber', ...options });\n\nexport const page = (options: PdfPage): PdfPage => options;\n\n/** A whole document; `version` is stamped for you. */\nexport const pdfDocument = (\n\toptions: Omit<PdfDocument, 'version'>,\n): PdfDocument => ({ ...options, version: 1 });\n\n/**\n * What `definePdfDocument` accepts: a function from your data (and more\n * parameters, if you like) to a document without its `version`. A method\n * signature, so that its parameters are checked both ways: an annotated\n * `(inv: Invoice)` fits, while an unannotated first parameter is typed\n * `unknown` (use it only after narrowing) and a later one with a default\n * (`language = 'en'`) takes its type from the default.\n */\ntype PdfTemplate = {\n\tbuild(data: unknown, ...rest: never[]): Omit<PdfDocument, 'version'>;\n}['build'];\n\n/**\n * Types a template: a function from your data to a document. It returns the\n * function unchanged, stamping `version` on what it builds. Annotate the\n * data parameter; the others may have defaults (`language = 'en'`). Left\n * unannotated, the data is `unknown`, so reading a property of it fails to\n * compile in the template rather than where the template is called.\n *\n * @example\n * const invoicePdf = definePdfDocument((inv: Invoice, language = 'en') => ({\n * language,\n * pages: [page({ pageNumbers: true, body: [heading(inv.number)] })],\n * }));\n */\nexport function definePdfDocument<F extends PdfTemplate>(\n\tbuild: F,\n): (...args: Parameters<F>) => PdfDocument {\n\t// `F`'s own parameters are what the returned function takes.\n\tconst run = build as unknown as (\n\t\t...args: Parameters<F>\n\t) => Omit<PdfDocument, 'version'>;\n\treturn (...args) => ({ ...run(...args), version: 1 });\n}\n",
|
|
6
|
-
"import {\n\ttype PrintColumn,\n\ttype PrintTableOptions,\n\tresolvePrintFields,\n\tresolvePrintTable,\n} from '../../lib/print-table.utils';\nimport type { PdfNode } from './types';\n\ntype TableNode = Extract<PdfNode, { type: 'table' }>;\ntype KeyValueNode = Extract<PdfNode, { type: 'keyValue' }>;\n\nexport type DataTableOptions = PrintTableOptions &\n\tPick<\n\t\tTableNode,\n\t\t'striped' | 'repeatHeader' | 'keepRowsWhole' | 'emptyText' | 'hideWhenEmpty'\n\t>;\n\n/**\n * A `table` node from column definitions and plain rows — the model twin of\n * `PrintDataTable`. Without `totalLabel`, the totals row reads \"Total\" in the\n * document's language.\n *\n * @example\n * dataTable(definePrintColumns<Line>([\n * { key: 'item', label: 'Item', flex: 3 },\n * { key: 'amount', label: 'Amount', format: 'amount', total: 'sum' },\n * ]), invoice.lines, { currency: 'EUR' })\n */\nexport function dataTable<T>(\n\tcolumns: PrintColumn<T>[],\n\trows: T[],\n\toptions: DataTableOptions = {},\n): TableNode {\n\tconst { currency, totalLabel, ...layout } = options;\n\tconst table = resolvePrintTable(columns, rows, { currency, totalLabel });\n\tconst labelTotals =\n\t\ttotalLabel === undefined &&
|
|
6
|
+
"import {\n\ttype PrintColumn,\n\ttype PrintTableOptions,\n\tresolvePrintFields,\n\tresolvePrintTable,\n} from '../../lib/print-table.utils';\nimport type { PdfNode } from './types';\n\ntype TableNode = Extract<PdfNode, { type: 'table' }>;\ntype KeyValueNode = Extract<PdfNode, { type: 'keyValue' }>;\n\nexport type DataTableOptions = PrintTableOptions &\n\tPick<\n\t\tTableNode,\n\t\t'striped' | 'repeatHeader' | 'keepRowsWhole' | 'emptyText' | 'hideWhenEmpty'\n\t>;\n\n/**\n * A `table` node from column definitions and plain rows — the model twin of\n * `PrintDataTable`. Without `totalLabel`, the totals row reads \"Total\" in the\n * document's language.\n *\n * @example\n * dataTable(definePrintColumns<Line>([\n * { key: 'item', label: 'Item', flex: 3 },\n * { key: 'amount', label: 'Amount', format: 'amount', total: 'sum' },\n * ]), invoice.lines, { currency: 'EUR' })\n */\nexport function dataTable<T>(\n\tcolumns: PrintColumn<T>[],\n\trows: T[],\n\toptions: DataTableOptions = {},\n): TableNode {\n\tconst { currency, totalLabel, ...layout } = options;\n\tconst table = resolvePrintTable(columns, rows, { currency, totalLabel });\n\tconst labelTotals =\n\t\ttotalLabel === undefined && columns[0] !== undefined && !columns[0].total;\n\tconst footer = labelTotals\n\t\t? table.footer.map(([, ...rest]) => [null, ...rest])\n\t\t: table.footer;\n\treturn {\n\t\ttype: 'table',\n\t\tcolumns: table.columns,\n\t\trows: table.rows,\n\t\t...(footer.length > 0 && { footer, ...(labelTotals && { labelTotals }) }),\n\t\t...layout,\n\t};\n}\n\n/** A `keyValue` node from one row, read through column definitions. */\nexport function keyValueOf<T>(\n\tfields: PrintColumn<T>[],\n\tdata: T,\n\toptions: Pick<PrintTableOptions, 'currency'> &\n\t\tPick<KeyValueNode, 'columns' | 'keepEmpty'> = {},\n): KeyValueNode {\n\tconst { currency, ...layout } = options;\n\treturn {\n\t\ttype: 'keyValue',\n\t\titems: resolvePrintFields(fields, data, { currency }),\n\t\t...layout,\n\t};\n}\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": ";;;;;;AAkBO,IAAM,QAAO,CACnB,SACA,UAA4C,CAAC,OACxB,EAAE,MAAM,QAAQ,YAAY,QAAQ;AAEnD,IAAM,WAAU,CAAC,MAAc,UACrC,QAAQ,EAAE,MAAM,WAAW,MAAM,MAAM,IAAI,EAAE,MAAM,WAAW,KAAK;AAE7D,IAAM,SAAQ,CACpB,UACA,UAA8C,CAAC,OACzB,EAAE,MAAM,SAAS,aAAa,QAAQ;AAEtD,IAAM,OAAM,CAClB,UACA,UAA4C,CAAC,OACzB,EAAE,MAAM,OAAO,aAAa,QAAQ;AAElD,IAAM,WAAU,CACtB,OACA,cACwB,EAAE,MAAM,WAAW,OAAO,SAAS;AAErD,IAAM,SAAQ,CACpB,KACA,UAAyC,CAAC,OACpB,EAAE,MAAM,SAAS,QAAQ,QAAQ;AAEjD,IAAM,QAAO,CAAC,MAAc,UAAkC;AAAA,EACpE,MAAM;AAAA,EACN;AAAA,EACA;AACD;AAEO,IAAM,UAAS,CAAC,UAAoC;AAAA,EAC1D,MAAM;AAAA,EACN;AACD;AAEO,IAAM,WAAU,OAA0B,EAAE,MAAM,UAAU;AAE5D,IAAM,aAAY,OAA4B,EAAE,MAAM,YAAY;AAElE,IAAM,SAAQ,CAAC,aAAgD;AAAA,EACrE,MAAM;AAAA,KACH;AACJ;AAEO,IAAM,YAAW,CACvB,OACA,UAA8C,CAAC,OACtB,EAAE,MAAM,YAAY,UAAU,QAAQ;AAEzD,IAAM,UAAS,CAAC,UAAsD;AAAA,EAC5E,MAAM;AAAA,EACN;AACD;AAEO,IAAM,UAAS,CAAC,aAAkD;AAAA,EACxE,MAAM;AAAA,KACH;AACJ;AAEO,IAAM,SAAQ,CAAC,MAAc,UACnC,QAAQ,EAAE,MAAM,SAAS,MAAM,MAAM,IAAI,EAAE,MAAM,SAAS,KAAK;AAEzD,IAAM,UAAS,CAAC,aAAkD;AAAA,EACxE,MAAM;AAAA,KACH;AACJ;AAEO,IAAM,cAAa,CACzB,UAAiC,CAAC,OACP,EAAE,MAAM,iBAAiB,QAAQ;AAEtD,IAAM,QAAO,CAAC,YAA8B;AAG5C,IAAM,eAAc,CAC1B,aACkB,KAAK,SAAS,SAAS,EAAE;AA2BrC,SAAS,kBAAwC,CACvD,OAC0C;AAAA,EAE1C,MAAM,MAAM;AAAA,EAGZ,OAAO,IAAI,UAAU,KAAK,IAAI,GAAG,IAAI,GAAG,SAAS,EAAE;AAAA;;;ACxG7C,SAAS,UAAY,CAC3B,SACA,MACA,UAA4B,CAAC,GACjB;AAAA,EACZ,QAAQ,UAAU,eAAe,WAAW;AAAA,EAC5C,MAAM,QAAQ,mBAAkB,SAAS,MAAM,EAAE,UAAU,WAAW,CAAC;AAAA,EACvE,MAAM,cACL,eAAe,aAAa,QAAQ,
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": ";;;;;;AAkBO,IAAM,QAAO,CACnB,SACA,UAA4C,CAAC,OACxB,EAAE,MAAM,QAAQ,YAAY,QAAQ;AAEnD,IAAM,WAAU,CAAC,MAAc,UACrC,QAAQ,EAAE,MAAM,WAAW,MAAM,MAAM,IAAI,EAAE,MAAM,WAAW,KAAK;AAE7D,IAAM,SAAQ,CACpB,UACA,UAA8C,CAAC,OACzB,EAAE,MAAM,SAAS,aAAa,QAAQ;AAEtD,IAAM,OAAM,CAClB,UACA,UAA4C,CAAC,OACzB,EAAE,MAAM,OAAO,aAAa,QAAQ;AAElD,IAAM,WAAU,CACtB,OACA,cACwB,EAAE,MAAM,WAAW,OAAO,SAAS;AAErD,IAAM,SAAQ,CACpB,KACA,UAAyC,CAAC,OACpB,EAAE,MAAM,SAAS,QAAQ,QAAQ;AAEjD,IAAM,QAAO,CAAC,MAAc,UAAkC;AAAA,EACpE,MAAM;AAAA,EACN;AAAA,EACA;AACD;AAEO,IAAM,UAAS,CAAC,UAAoC;AAAA,EAC1D,MAAM;AAAA,EACN;AACD;AAEO,IAAM,WAAU,OAA0B,EAAE,MAAM,UAAU;AAE5D,IAAM,aAAY,OAA4B,EAAE,MAAM,YAAY;AAElE,IAAM,SAAQ,CAAC,aAAgD;AAAA,EACrE,MAAM;AAAA,KACH;AACJ;AAEO,IAAM,YAAW,CACvB,OACA,UAA8C,CAAC,OACtB,EAAE,MAAM,YAAY,UAAU,QAAQ;AAEzD,IAAM,UAAS,CAAC,UAAsD;AAAA,EAC5E,MAAM;AAAA,EACN;AACD;AAEO,IAAM,UAAS,CAAC,aAAkD;AAAA,EACxE,MAAM;AAAA,KACH;AACJ;AAEO,IAAM,SAAQ,CAAC,MAAc,UACnC,QAAQ,EAAE,MAAM,SAAS,MAAM,MAAM,IAAI,EAAE,MAAM,SAAS,KAAK;AAEzD,IAAM,UAAS,CAAC,aAAkD;AAAA,EACxE,MAAM;AAAA,KACH;AACJ;AAEO,IAAM,cAAa,CACzB,UAAiC,CAAC,OACP,EAAE,MAAM,iBAAiB,QAAQ;AAEtD,IAAM,QAAO,CAAC,YAA8B;AAG5C,IAAM,eAAc,CAC1B,aACkB,KAAK,SAAS,SAAS,EAAE;AA2BrC,SAAS,kBAAwC,CACvD,OAC0C;AAAA,EAE1C,MAAM,MAAM;AAAA,EAGZ,OAAO,IAAI,UAAU,KAAK,IAAI,GAAG,IAAI,GAAG,SAAS,EAAE;AAAA;;;ACxG7C,SAAS,UAAY,CAC3B,SACA,MACA,UAA4B,CAAC,GACjB;AAAA,EACZ,QAAQ,UAAU,eAAe,WAAW;AAAA,EAC5C,MAAM,QAAQ,mBAAkB,SAAS,MAAM,EAAE,UAAU,WAAW,CAAC;AAAA,EACvE,MAAM,cACL,eAAe,aAAa,QAAQ,OAAO,aAAa,CAAC,QAAQ,GAAG;AAAA,EACrE,MAAM,SAAS,cACZ,MAAM,OAAO,IAAI,OAAO,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,IACjD,MAAM;AAAA,EACT,OAAO;AAAA,IACN,MAAM;AAAA,IACN,SAAS,MAAM;AAAA,IACf,MAAM,MAAM;AAAA,OACR,OAAO,SAAS,KAAK,EAAE,WAAY,eAAe,EAAE,YAAY,EAAG;AAAA,OACpE;AAAA,EACJ;AAAA;AAIM,SAAS,WAAa,CAC5B,QACA,MACA,UAC+C,CAAC,GACjC;AAAA,EACf,QAAQ,aAAa,WAAW;AAAA,EAChC,OAAO;AAAA,IACN,MAAM;AAAA,IACN,OAAO,oBAAmB,QAAQ,MAAM,EAAE,SAAS,CAAC;AAAA,OACjD;AAAA,EACJ;AAAA;",
|
|
9
|
+
"debugId": "0A73B8345AA198A764756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/lib/print-format.utils.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Amount and date formatting, written for printed documents and used\n * everywhere.\n *\n * This lives in `lib/` because it depends on nothing but `Intl`, so a screen\n * that formats an amount never imports the print entry and its optional\n * peers. The print entry re-exports it.\n *\n * Without a `locale`, the runtime's locale applies (as before); pass one, or\n * use `useFormatters()`, for output that is the same on a server and in the\n * browser.\n */\n\nimport { fractionDigitsOption } from './print-fraction-digits';\n\nconst EMPTY = '—';\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport type FormatAmountOptions = {\n\t/** BCP 47 locale, such as `'fr-FR'`. Defaults to the runtime's locale. */\n\tlocale?: string;\n\t/**\n\t * Decimals to show, 0 to 20. With a currency it defaults to the\n\t * currency's own (ISO 4217: JPY 0, EUR 2, KWD 3); without one, to 2. Pass\n\t * `2` to keep two decimals whatever the currency. `NaN` or `Infinity`\n\t * counts as not given.\n\t */\n\tfractionDigits?: number;\n};\n\nexport type FormatDateOptions = {\n\t/** BCP 47 locale, such as `'fr-FR'`. Defaults to the runtime's locale. */\n\tlocale?: string;\n\t/**\n\t * IANA time zone for values with a time, such as `'Europe/Paris'`.\n\t * Defaults to the runtime's. A date-only value (`'2026-03-01'`) ignores it\n\t * and always shows its own calendar day.\n\t */\n\ttimeZone?: string;\n\t/** Defaults to `'medium'` (`Mar 1, 2026`). */\n\tdateStyle?: 'full' | 'long' | 'medium' | 'short';\n\t/** Adds the time; ignored for a date-only value. */\n\ttimeStyle?: 'full' | 'long' | 'medium' | 'short';\n};\n\nexport type DateInput = string | number | Date | null | undefined;\n\n/**\n * Formats an amount, in a currency when one is given. `null` and\n * `undefined` give `'—'`.\n *\n * @example formatAmount(1234.5, 'EUR', { locale: 'fr-FR' }) // '1 234,50 €'\n * @example formatAmount(1234.5, 'JPY', { locale: 'en-US' }) // '¥1,235'\n */\nexport function formatAmount(\n\tvalue: number | null | undefined,\n\tcurrency?: string | null,\n\toptions: FormatAmountOptions = {},\n): string {\n\tif (value == null) return EMPTY;\n\tconst { locale, fractionDigits } = options;\n\tconst digits =\n\t\tfractionDigitsOption(fractionDigits) ?? (currency ? undefined : 2);\n\ttry {\n\t\treturn new Intl.NumberFormat(locale, {\n\t\t\tstyle: currency ? 'currency' : 'decimal',\n\t\t\tcurrency: currency || undefined,\n\t\t\tminimumFractionDigits: digits,\n\t\t\tmaximumFractionDigits: digits,\n\t\t}).format(value);\n\t} catch {\n\t\treturn `${value.toFixed(digits ?? 2)}${currency ? ` ${currency}` : ''}`;\n\t}\n}\n\n/**\n * Formats a date. A date-only string (`YYYY-MM-DD`) keeps its calendar day\n * in every time zone; other values are shown in `timeZone`. Empty values\n * give `'—'`; a string that is not a date is returned as it is.\n *\n * @example formatDate('2026-03-01', { locale: 'en-US' }) // 'Mar 1, 2026'\n */\nexport function formatDate(\n\tvalue: DateInput,\n\toptions: FormatDateOptions = {},\n): string {\n\tif (value == null || value === '') return EMPTY;\n\tconst { locale, timeZone, dateStyle = 'medium', timeStyle } = options;\n\tconst dateOnly = typeof value === 'string' ? DATE_ONLY.exec(value) : null;\n\ttry {\n\t\tif (dateOnly) {\n\t\t\tconst [, year, month, day] = dateOnly;\n\t\t\tconst utc = new Date(0);\n\t\t\tutc.setUTCFullYear(+year, +month - 1, +day);\n\t\t\t// `2024-02-31` or `2024-13-01` rolls over: not a date.\n\t\t\tif (utc.getUTCMonth() !== +month - 1 || utc.getUTCDate() !== +day) {\n\t\t\t\treturn value as string;\n\t\t\t}\n\t\t\treturn new Intl.DateTimeFormat(locale, {\n\t\t\t\tdateStyle,\n\t\t\t\ttimeZone: 'UTC',\n\t\t\t}).format(utc);\n\t\t}\n\t\tconst date = value instanceof Date ? value : new Date(value);\n\t\tif (Number.isNaN(date.getTime())) {\n\t\t\treturn typeof value === 'string' ? value : EMPTY;\n\t\t}\n\t\treturn new Intl.DateTimeFormat(locale, {\n\t\t\tdateStyle,\n\t\t\ttimeStyle,\n\t\t\ttimeZone,\n\t\t}).format(date);\n\t} catch {\n\t\treturn typeof value === 'string' ? value : EMPTY;\n\t}\n}\n\nexport type FormattersOptions = {\n\tlocale?: string;\n\ttimeZone?: string;\n};\n\nexport type Formatters = {\n\tformatAmount: (\n\t\tvalue: number | null | undefined,\n\t\tcurrency?: string | null,\n\t\toptions?: FormatAmountOptions,\n\t) => string;\n\tformatDate: (value: DateInput, options?: FormatDateOptions) => string;\n};\n\n/**\n * `formatAmount` and `formatDate` bound to a locale and a time zone, for a\n * server route or a document builder. Options given per call win, unless\n * they are `undefined`.\n *\n * @example\n * const { formatAmount, formatDate } = createFormatters({ locale: 'fr-FR', timeZone: 'Europe/Paris' });\n */\nexport function createFormatters(defaults: FormattersOptions = {}): Formatters {\n\treturn {\n\t\tformatAmount: (value, currency, options) =>\n\t\t\tformatAmount(value, currency, {\n\t\t\t\t...options,\n\t\t\t\tlocale: options?.locale ?? defaults.locale,\n\t\t\t}),\n\t\tformatDate: (value, options) =>\n\t\t\tformatDate(value, {\n\t\t\t\t...options,\n\t\t\t\tlocale: options?.locale ?? defaults.locale,\n\t\t\t\ttimeZone: options?.timeZone ?? defaults.timeZone,\n\t\t\t}),\n\t};\n}\n"
|
|
5
|
+
"/**\n * Amount and date formatting, written for printed documents and used\n * everywhere.\n *\n * This lives in `lib/` because it depends on nothing but `Intl`, so a screen\n * that formats an amount never imports the print entry and its optional\n * peers. The print entry re-exports it.\n *\n * Without a `locale`, the runtime's locale applies (as before); pass one, or\n * use `useFormatters()`, for output that is the same on a server and in the\n * browser.\n */\n\nimport { fractionDigitsOption } from './print-fraction-digits';\n\nconst EMPTY = '—';\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport type FormatAmountOptions = {\n\t/** BCP 47 locale, such as `'fr-FR'`. Defaults to the runtime's locale. */\n\tlocale?: string;\n\t/**\n\t * Decimals to show, 0 to 20. With a currency it defaults to the\n\t * currency's own (ISO 4217: JPY 0, EUR 2, KWD 3); without one, to 2. Pass\n\t * `2` to keep two decimals whatever the currency. `NaN` or `Infinity`\n\t * counts as not given.\n\t */\n\tfractionDigits?: number;\n};\n\nexport type FormatDateOptions = {\n\t/** BCP 47 locale, such as `'fr-FR'`. Defaults to the runtime's locale. */\n\tlocale?: string;\n\t/**\n\t * IANA time zone for values with a time, such as `'Europe/Paris'`.\n\t * Defaults to the runtime's. A date-only value (`'2026-03-01'`) ignores it\n\t * and always shows its own calendar day.\n\t */\n\ttimeZone?: string;\n\t/** Defaults to `'medium'` (`Mar 1, 2026`). */\n\tdateStyle?: 'full' | 'long' | 'medium' | 'short';\n\t/** Adds the time; ignored for a date-only value. */\n\ttimeStyle?: 'full' | 'long' | 'medium' | 'short';\n};\n\nexport type DateInput = string | number | Date | null | undefined;\n\n/**\n * Formats an amount, in a currency when one is given. `null` and\n * `undefined` give `'—'`.\n *\n * @example formatAmount(1234.5, 'EUR', { locale: 'fr-FR' }) // '1 234,50 €'\n * @example formatAmount(1234.5, 'JPY', { locale: 'en-US' }) // '¥1,235'\n */\nexport function formatAmount(\n\tvalue: number | null | undefined,\n\tcurrency?: string | null,\n\toptions: FormatAmountOptions = {},\n): string {\n\tif (value == null) return EMPTY;\n\tconst { locale, fractionDigits } = options;\n\tconst digits =\n\t\tfractionDigitsOption(fractionDigits) ?? (currency ? undefined : 2);\n\ttry {\n\t\treturn new Intl.NumberFormat(locale, {\n\t\t\tstyle: currency ? 'currency' : 'decimal',\n\t\t\tcurrency: currency || undefined,\n\t\t\tminimumFractionDigits: digits,\n\t\t\tmaximumFractionDigits: digits,\n\t\t}).format(value);\n\t} catch {\n\t\treturn `${value.toFixed(digits ?? 2)}${currency ? ` ${currency}` : ''}`;\n\t}\n}\n\n/**\n * Formats a date. A date-only string (`YYYY-MM-DD`) keeps its calendar day\n * in every time zone; other values are shown in `timeZone`. Empty values\n * give `'—'`; a string that is not a date is returned as it is.\n *\n * @example formatDate('2026-03-01', { locale: 'en-US' }) // 'Mar 1, 2026'\n */\nexport function formatDate(\n\tvalue: DateInput,\n\toptions: FormatDateOptions = {},\n): string {\n\tif (value == null || value === '') return EMPTY;\n\tconst { locale, timeZone, dateStyle = 'medium', timeStyle } = options;\n\tconst dateOnly = typeof value === 'string' ? DATE_ONLY.exec(value) : null;\n\ttry {\n\t\tif (dateOnly) {\n\t\t\t// DATE_ONLY's three groups are not optional: a match holds all three.\n\t\t\tconst [, year, month, day] = dateOnly as unknown as [\n\t\t\t\tstring,\n\t\t\t\tstring,\n\t\t\t\tstring,\n\t\t\t\tstring,\n\t\t\t];\n\t\t\tconst utc = new Date(0);\n\t\t\tutc.setUTCFullYear(+year, +month - 1, +day);\n\t\t\t// `2024-02-31` or `2024-13-01` rolls over: not a date.\n\t\t\tif (utc.getUTCMonth() !== +month - 1 || utc.getUTCDate() !== +day) {\n\t\t\t\treturn value as string;\n\t\t\t}\n\t\t\treturn new Intl.DateTimeFormat(locale, {\n\t\t\t\tdateStyle,\n\t\t\t\ttimeZone: 'UTC',\n\t\t\t}).format(utc);\n\t\t}\n\t\tconst date = value instanceof Date ? value : new Date(value);\n\t\tif (Number.isNaN(date.getTime())) {\n\t\t\treturn typeof value === 'string' ? value : EMPTY;\n\t\t}\n\t\treturn new Intl.DateTimeFormat(locale, {\n\t\t\tdateStyle,\n\t\t\ttimeStyle,\n\t\t\ttimeZone,\n\t\t}).format(date);\n\t} catch {\n\t\treturn typeof value === 'string' ? value : EMPTY;\n\t}\n}\n\nexport type FormattersOptions = {\n\tlocale?: string;\n\ttimeZone?: string;\n};\n\nexport type Formatters = {\n\tformatAmount: (\n\t\tvalue: number | null | undefined,\n\t\tcurrency?: string | null,\n\t\toptions?: FormatAmountOptions,\n\t) => string;\n\tformatDate: (value: DateInput, options?: FormatDateOptions) => string;\n};\n\n/**\n * `formatAmount` and `formatDate` bound to a locale and a time zone, for a\n * server route or a document builder. Options given per call win, unless\n * they are `undefined`.\n *\n * @example\n * const { formatAmount, formatDate } = createFormatters({ locale: 'fr-FR', timeZone: 'Europe/Paris' });\n */\nexport function createFormatters(defaults: FormattersOptions = {}): Formatters {\n\treturn {\n\t\tformatAmount: (value, currency, options) =>\n\t\t\tformatAmount(value, currency, {\n\t\t\t\t...options,\n\t\t\t\tlocale: options?.locale ?? defaults.locale,\n\t\t\t}),\n\t\tformatDate: (value, options) =>\n\t\t\tformatDate(value, {\n\t\t\t\t...options,\n\t\t\t\tlocale: options?.locale ?? defaults.locale,\n\t\t\t\ttimeZone: options?.timeZone ?? defaults.timeZone,\n\t\t\t}),\n\t};\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";;;;;AAeA,IAAM,QAAQ;AACd,IAAM,YAAY;AAsCX,SAAS,aAAY,CAC3B,OACA,UACA,UAA+B,CAAC,GACvB;AAAA,EACT,IAAI,SAAS;AAAA,IAAM,OAAO;AAAA,EAC1B,QAAQ,QAAQ,mBAAmB;AAAA,EACnC,MAAM,SACL,sBAAqB,cAAc,MAAM,WAAW,YAAY;AAAA,EACjE,IAAI;AAAA,IACH,OAAO,IAAI,KAAK,aAAa,QAAQ;AAAA,MACpC,OAAO,WAAW,aAAa;AAAA,MAC/B,UAAU,YAAY;AAAA,MACtB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,IACxB,CAAC,EAAE,OAAO,KAAK;AAAA,IACd,MAAM;AAAA,IACP,OAAO,GAAG,MAAM,QAAQ,UAAU,CAAC,IAAI,WAAW,IAAI,aAAa;AAAA;AAAA;AAW9D,SAAS,WAAU,CACzB,OACA,UAA6B,CAAC,GACrB;AAAA,EACT,IAAI,SAAS,QAAQ,UAAU;AAAA,IAAI,OAAO;AAAA,EAC1C,QAAQ,QAAQ,UAAU,YAAY,UAAU,cAAc;AAAA,EAC9D,MAAM,WAAW,OAAO,UAAU,WAAW,UAAU,KAAK,KAAK,IAAI;AAAA,EACrE,IAAI;AAAA,IACH,IAAI,UAAU;AAAA,
|
|
7
|
+
"mappings": ";;;;;AAeA,IAAM,QAAQ;AACd,IAAM,YAAY;AAsCX,SAAS,aAAY,CAC3B,OACA,UACA,UAA+B,CAAC,GACvB;AAAA,EACT,IAAI,SAAS;AAAA,IAAM,OAAO;AAAA,EAC1B,QAAQ,QAAQ,mBAAmB;AAAA,EACnC,MAAM,SACL,sBAAqB,cAAc,MAAM,WAAW,YAAY;AAAA,EACjE,IAAI;AAAA,IACH,OAAO,IAAI,KAAK,aAAa,QAAQ;AAAA,MACpC,OAAO,WAAW,aAAa;AAAA,MAC/B,UAAU,YAAY;AAAA,MACtB,uBAAuB;AAAA,MACvB,uBAAuB;AAAA,IACxB,CAAC,EAAE,OAAO,KAAK;AAAA,IACd,MAAM;AAAA,IACP,OAAO,GAAG,MAAM,QAAQ,UAAU,CAAC,IAAI,WAAW,IAAI,aAAa;AAAA;AAAA;AAW9D,SAAS,WAAU,CACzB,OACA,UAA6B,CAAC,GACrB;AAAA,EACT,IAAI,SAAS,QAAQ,UAAU;AAAA,IAAI,OAAO;AAAA,EAC1C,QAAQ,QAAQ,UAAU,YAAY,UAAU,cAAc;AAAA,EAC9D,MAAM,WAAW,OAAO,UAAU,WAAW,UAAU,KAAK,KAAK,IAAI;AAAA,EACrE,IAAI;AAAA,IACH,IAAI,UAAU;AAAA,MAEb,SAAS,MAAM,OAAO,OAAO;AAAA,MAM7B,MAAM,MAAM,IAAI,KAAK,CAAC;AAAA,MACtB,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,GAAG;AAAA,MAE1C,IAAI,IAAI,YAAY,MAAM,CAAC,QAAQ,KAAK,IAAI,WAAW,MAAM,CAAC,KAAK;AAAA,QAClE,OAAO;AAAA,MACR;AAAA,MACA,OAAO,IAAI,KAAK,eAAe,QAAQ;AAAA,QACtC;AAAA,QACA,UAAU;AAAA,MACX,CAAC,EAAE,OAAO,GAAG;AAAA,IACd;AAAA,IACA,MAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,KAAK;AAAA,IAC3D,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,GAAG;AAAA,MACjC,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,IAC5C;AAAA,IACA,OAAO,IAAI,KAAK,eAAe,QAAQ;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,IACD,CAAC,EAAE,OAAO,IAAI;AAAA,IACb,MAAM;AAAA,IACP,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA;AAAA;AA0BtC,SAAS,iBAAgB,CAAC,WAA8B,CAAC,GAAe;AAAA,EAC9E,OAAO;AAAA,IACN,cAAc,CAAC,OAAO,UAAU,YAC/B,cAAa,OAAO,UAAU;AAAA,SAC1B;AAAA,MACH,QAAQ,SAAS,UAAU,SAAS;AAAA,IACrC,CAAC;AAAA,IACF,YAAY,CAAC,OAAO,YACnB,YAAW,OAAO;AAAA,SACd;AAAA,MACH,QAAQ,SAAS,UAAU,SAAS;AAAA,MACpC,UAAU,SAAS,YAAY,SAAS;AAAA,IACzC,CAAC;AAAA,EACH;AAAA;",
|
|
8
8
|
"debugId": "DD36C19E6625613264756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print-format.utils.d.ts","sourceRoot":"","sources":["../../src/lib/print-format.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,MAAM,mBAAmB,GAAG;IACjC,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACjD,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,GAAE,mBAAwB,GAC/B,MAAM,CAeR;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACzB,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,iBAAsB,GAC7B,MAAM,
|
|
1
|
+
{"version":3,"file":"print-format.utils.d.ts","sourceRoot":"","sources":["../../src/lib/print-format.utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,MAAM,mBAAmB,GAAG;IACjC,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC/B,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACjD,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,GAAE,mBAAwB,GAC/B,MAAM,CAeR;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACzB,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,iBAAsB,GAC7B,MAAM,CAoCR;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACxB,YAAY,EAAE,CACb,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,CAAC,EAAE,mBAAmB,KACzB,MAAM,CAAC;IACZ,UAAU,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,iBAAiB,KAAK,MAAM,CAAC;CACtE,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,GAAE,iBAAsB,GAAG,UAAU,CAc7E"}
|
package/dist/pdf/index.js
CHANGED
package/dist/pdf/model/index.js
CHANGED
package/docs/roadmap.md
CHANGED
|
@@ -5,12 +5,7 @@ version an item shipped in is the only number on this page.
|
|
|
5
5
|
|
|
6
6
|
## Now
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
shared file by file — the PDF model and renderer, the print formatters, the
|
|
10
|
-
PDF file helpers, the PDF reader's framework-free modules (`/pdf-viewer`:
|
|
11
|
-
search, geometry, page sizes, scroll spy), the currency digits, the fields'
|
|
12
|
-
blur layers and the fonts plugin — is this one package, and both libraries
|
|
13
|
-
depend on it.
|
|
8
|
+
Nothing in progress right now; see Next.
|
|
14
9
|
|
|
15
10
|
## Next
|
|
16
11
|
|
|
@@ -33,3 +28,12 @@ version an item shipped in is the only number on this page.
|
|
|
33
28
|
- **Test helpers.** Reading a rendered PDF back and the fake DOM the
|
|
34
29
|
libraries' tests use are the repository's own, in a private package that is
|
|
35
30
|
never published.
|
|
31
|
+
|
|
32
|
+
## Shipped
|
|
33
|
+
|
|
34
|
+
- **A first release** — the PDF model and renderer, the print formatters,
|
|
35
|
+
the PDF file helpers, the PDF reader's framework-free modules
|
|
36
|
+
(`/pdf-viewer`: search, geometry, page sizes, scroll spy), the currency
|
|
37
|
+
digits, the fields' blur layers and the fonts plugin, which
|
|
38
|
+
`@nxgt/material` and `@nxgt/material-vue` shared file by file, are this one
|
|
39
|
+
package, and both libraries depend on it. 0.1.0.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/material-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "The framework-free core of @nxgt/material and @nxgt/material-vue: the PDF document model and its react-pdf renderer, print formatters, PDF file helpers, the PDF viewer's pure modules, the currency digits, the field-blur layers and the pdfkit fonts Vite plugin",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": {
|
|
@@ -115,11 +115,6 @@
|
|
|
115
115
|
"framework-agnostic",
|
|
116
116
|
"typescript"
|
|
117
117
|
],
|
|
118
|
-
"repository": {
|
|
119
|
-
"type": "git",
|
|
120
|
-
"url": "git+https://github.com/softistx/nxgt-material.git",
|
|
121
|
-
"directory": "packages/core"
|
|
122
|
-
},
|
|
123
118
|
"publishConfig": {
|
|
124
119
|
"registry": "https://registry.npmjs.org",
|
|
125
120
|
"access": "public"
|