@nxgt/material-core 0.3.1 → 0.4.0
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/CHANGELOG.md +156 -0
- package/README.md +19 -0
- package/dist/lib/row-activation.d.ts +30 -0
- package/dist/lib/row-activation.d.ts.map +1 -0
- package/dist/lib/row-activation.js +62 -0
- package/dist/lib/row-activation.js.map +10 -0
- package/docs/roadmap.md +4 -0
- package/package.json +8 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# @nxgt/material-core
|
|
2
|
+
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#431](https://github.com/softistx/nxgt-material/pull/431) [`bd58a6f`](https://github.com/softistx/nxgt-material/commit/bd58a6f67bdc25d4b4d0d7d88c52784869ad1529) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `DataTable` renders server-side data: one page from a loader, with the query in the URL. Everything is opt-in; a table that sets none of the new props renders and behaves as before.
|
|
8
|
+
|
|
9
|
+
- `manual`: `data` is one server page, rendered as given — no client paging, sorting or filtering — and the footer becomes `DataTableServerFooter` (exported).
|
|
10
|
+
- `pagination={{ totalCount, offset, previous, next }}`: the server footer's range ("41–60 of 133", `material.table.pagination.range`) and Previous / Next, each an href (a real link, `rel="prev"` / `rel="next"`, that works with no JavaScript) or a callback (a button); disabled when absent and while `loading`.
|
|
11
|
+
- Controlled sorting: `sorting` + `onSortingChange(sorting)` in React, `v-model:sorting` in Vue. The headers show the sorting they are given; the callback receives the new `SortingState`, not an updater.
|
|
12
|
+
- `getRowId(row, index)` and controlled selection by id: `rowSelection` + `onRowSelectionChange(selection)` in React, `v-model:row-selection` in Vue. Ids of other pages are kept, and the server footer counts them all.
|
|
13
|
+
- `getRowHref(row)`: the first data cell becomes a link to the row's page, and a click anywhere else on the row (but on a control, in a portal, or at the end of a text selection) follows it. `onRowClick(row, event)` (`@row-click` in Vue) makes the row focusable and activatable with Enter.
|
|
14
|
+
- `linkComponent`: the link rendered for row and page links, given `href` (wrap React Router's `Link` or vue-router's `RouterLink`, which take `to`). Default: a plain `<a>`.
|
|
15
|
+
- `footer`: a render function (React, Vue) or the `#footer` slot (Vue) replaces the footer; `footer={false}` removes it.
|
|
16
|
+
- New `material.table.pagination.*` strings, in English and French: `label`, `range`, `range-open`, `total`, `selected`.
|
|
17
|
+
|
|
18
|
+
`@nxgt/material-core` gains `/row-activation` (`isRowActivation`, `followRowLink`, `ROW_CONTROL_SELECTOR`, `ROW_LINK_SELECTOR`, `RowClick`): the clickable-row rule both libraries' `DataTable` use.
|
|
19
|
+
|
|
20
|
+
## 0.3.2
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- [#429](https://github.com/softistx/nxgt-material/pull/429) [`13c3eda`](https://github.com/softistx/nxgt-material/commit/13c3edad01f08656ca196aca7c37a21e8c003466) Thanks [@SteveGT96](https://github.com/SteveGT96)! - The package ships its `CHANGELOG.md` (now in `files`), so the notes of every
|
|
25
|
+
version are in `node_modules/<package>/CHANGELOG.md` next to the docs, for
|
|
26
|
+
reading offline and for the upgrade agents of the Claude Code plugins.
|
|
27
|
+
The getting-started pages of `@nxgt/material` and `@nxgt/material-vue`
|
|
28
|
+
list it among the tarball's contents.
|
|
29
|
+
|
|
30
|
+
## 0.3.1
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- [#427](https://github.com/softistx/nxgt-material/pull/427) [`d4e953f`](https://github.com/softistx/nxgt-material/commit/d4e953fd4fc147b366c5d9d70ebfb1aa3a3c0ba7) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Docs: the roadmap lists what 0.3.0 shipped (`/date-range`, `/file-preview`, `/slider-ticks`) under Shipped, newest first. Troubleshooting has entries for `FilePreviewHttpError` (`Could not read <url>: HTTP <status>`) and `FilePreviewUnsafeUrlError` (`Refused to preview a URL with an unsafe scheme`), so every message the package prints is there again. The README's `/pdf-viewer` section documents `pinToPage`'s `onRelease` and `pinHolds`, with an example.
|
|
35
|
+
|
|
36
|
+
## 0.3.0
|
|
37
|
+
|
|
38
|
+
### Minor Changes
|
|
39
|
+
|
|
40
|
+
- [#424](https://github.com/softistx/nxgt-material/pull/424) [`d90a68b`](https://github.com/softistx/nxgt-material/commit/d90a68b8f16759b44929effc426b6c3964e92a4c) Thanks [@SteveGT96](https://github.com/SteveGT96)! - New subpath `/date-range`, the pure half of both libraries' `DateRangeField`
|
|
41
|
+
presets and times: `DATE_RANGE_PRESET_IDS` (`today`, `yesterday`,
|
|
42
|
+
`last-7-days`, `last-30-days`, `this-month`, `last-month`, `this-year`),
|
|
43
|
+
`presetRange(id, now?)`, `resolvePresetRange(preset, now?, { withTime })`,
|
|
44
|
+
`isSameDayRange`, `isRangeDisabled(range, { min, max, isDayDisabled })`
|
|
45
|
+
(also true for a range whose end comes before its start),
|
|
46
|
+
`withTimeOf`, `endOfDayTime`, `clampRangeEnd`, `keepRangeTimes` (a new end
|
|
47
|
+
at 23:59), and the types
|
|
48
|
+
`DayRange`, `PartialDayRange`, `DateRangePreset`, `DateRangePresetId`,
|
|
49
|
+
`DateRangePresetOption` and `DateRangeRules`.
|
|
50
|
+
|
|
51
|
+
- [#426](https://github.com/softistx/nxgt-material/pull/426) [`812c101`](https://github.com/softistx/nxgt-material/commit/812c10115278480852852084ddf06b016239e6d4) Thanks [@SteveGT96](https://github.com/SteveGT96)! - New subpath `/file-preview`, the pure half of both libraries' `FilePreview`:
|
|
52
|
+
`fileKind({ type, name, url })` picks a `FileKind` (`image`, `pdf`, `video`,
|
|
53
|
+
`audio`, `text`, `json`, `csv`, `markdown` or `other`) from the MIME type
|
|
54
|
+
when it names one (a `data:` URL's included), else from the extension of the
|
|
55
|
+
name, then of the URL; `describeFile(file, { type, name })` does it for a
|
|
56
|
+
`File` / `Blob` or a URL and returns its name, type and size;
|
|
57
|
+
`safePreviewUrl(url)` returns the URL when it may reach an `href` or a `src`
|
|
58
|
+
(`http(s):`, relative, `blob:`, or a `data:` URL of an image, video, audio
|
|
59
|
+
file, plain text, CSV, Markdown, JSON or PDF) and `null` for anything else
|
|
60
|
+
(`javascript:`, `data:text/html`, and also a `data:` URL of XML, TSV or
|
|
61
|
+
YAML), with `FilePreviewUnsafeUrlError` ("Refused to preview a URL with an unsafe scheme") for the one refused;
|
|
62
|
+
`readTextPreview(source, { maxBytes, signal })` reads the first `maxBytes`
|
|
63
|
+
(`TEXT_PREVIEW_MAX_BYTES`, 256 KB, by default) of a `Blob` or of what a URL
|
|
64
|
+
answers, decoded with the `charset` of the `Content-Type` (or of the `Blob`'s
|
|
65
|
+
`type`) when `TextDecoder` supports it and as UTF-8 otherwise, stopping the
|
|
66
|
+
download past the cap; it throws `FilePreviewHttpError` (with its `status`)
|
|
67
|
+
on an HTTP error, and rejects with the signal's reason once aborted, for a
|
|
68
|
+
`Blob` too. Also
|
|
69
|
+
`fileExtension`, `fileNameFromUrl`, `dataUrlType`, `kindOfMimeType`,
|
|
70
|
+
`normaliseMimeType`, `isTextFileKind`, `TEXT_FILE_KINDS` and the types
|
|
71
|
+
`FileKind`, `FileKindInput`, `DescribedFile`, `FilePreviewSource` and
|
|
72
|
+
`TextPreview`. Nothing runs at import.
|
|
73
|
+
|
|
74
|
+
- [#420](https://github.com/softistx/nxgt-material/pull/420) [`f4ca69b`](https://github.com/softistx/nxgt-material/commit/f4ca69ba5dd7b80f92cdd5374cf6fd01f155784d) Thanks [@SteveGT96](https://github.com/SteveGT96)! - New subpath `/slider-ticks`: `tickValues(min, max, ticks, step?)`, the values a slider's tick marks sit at. Both libraries' `SliderField` (`ticks`) now read it from here instead of keeping a copy each.
|
|
75
|
+
|
|
76
|
+
### Patch Changes
|
|
77
|
+
|
|
78
|
+
- [#419](https://github.com/softistx/nxgt-material/pull/419) [`99878c9`](https://github.com/softistx/nxgt-material/commit/99878c9bdb0d4c33fd6a777970c4f3735bd5ef3b) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `PdfReader`: opening on an `initialPage` no longer reports another page on a
|
|
79
|
+
slow device. The placement scroll could land after the scroll spy's hold had
|
|
80
|
+
run out, and near the end of the document it read as the last page. While
|
|
81
|
+
the view stays where the opening page's pin put it (that page at the top,
|
|
82
|
+
or the page area at its end with that page not above the top), a scroll is the reader's own and is not
|
|
83
|
+
reported; a scroll that moves the view elsewhere — the user's, find in page,
|
|
84
|
+
a screen reader's cursor — lets go of the pin and is reported. A wheel,
|
|
85
|
+
touch, pointer or key in the page area also ends the hold on the reader's
|
|
86
|
+
own scroll, so the scrolling after it is reported at once. In
|
|
87
|
+
`@nxgt/material-core/pdf-viewer`, `pinToPage` takes an optional `onRelease`,
|
|
88
|
+
called once when the pin lets go, and `pinHolds(node)` tells whether the view
|
|
89
|
+
is still where the pin puts it.
|
|
90
|
+
|
|
91
|
+
## 0.2.0
|
|
92
|
+
|
|
93
|
+
### Minor Changes
|
|
94
|
+
|
|
95
|
+
- [#406](https://github.com/softistx/nxgt-material/pull/406) [`b890457`](https://github.com/softistx/nxgt-material/commit/b8904573f18dc6d0cdd16f62146183ff0b7aef18) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Two new subpaths, each the one copy of code `@nxgt/material` and
|
|
96
|
+
`@nxgt/material-vue` used to keep twice:
|
|
97
|
+
|
|
98
|
+
- **`@nxgt/material-core/format-file-size`**: `formatFileSize(bytes)`, the
|
|
99
|
+
byte count both libraries' `FileList`, `NetworkUploadField`, `FileCard` and
|
|
100
|
+
chat attachments show (`'1.5 KB'`; `''` for a negative, `NaN` or infinite
|
|
101
|
+
size).
|
|
102
|
+
- **`@nxgt/material-core/pdfkit-fonts`** (Node only): `pdfkitStandardFontDirs`,
|
|
103
|
+
`pdfkitStandardFontFiles` and `PDFKIT_STANDARD_FONTS` find the real files of
|
|
104
|
+
pdfkit's standard fonts as an app loads them, through `@react-pdf/renderer`
|
|
105
|
+
and `@react-pdf/font`, for a server tracer (`@nxgt/material/next`, the Nuxt
|
|
106
|
+
module of `@nxgt/material-vue`). Without `@react-pdf/renderer` they return
|
|
107
|
+
`[]` silently; any other failure reaches your `warn` callback once per
|
|
108
|
+
call. It is the only subpath that imports `node:` built-ins: never import it
|
|
109
|
+
from browser code.
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { formatFileSize } from '@nxgt/material-core/format-file-size';
|
|
113
|
+
import { pdfkitStandardFontDirs } from '@nxgt/material-core/pdfkit-fonts';
|
|
114
|
+
|
|
115
|
+
formatFileSize(1536); // '1.5 KB'
|
|
116
|
+
pdfkitStandardFontDirs(process.cwd(), console.warn); // ['/app/node_modules/pdfkit/js/standard-fonts']
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Patch Changes
|
|
120
|
+
|
|
121
|
+
- [#407](https://github.com/softistx/nxgt-material/pull/407) [`bf43a14`](https://github.com/softistx/nxgt-material/commit/bf43a14abb147e6dcd2bcac5f1e0e359b0aae6a2) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `pdfkitStandardFontDirs` and `pdfkitStandardFontFiles` (`/pdfkit-fonts`) keep
|
|
122
|
+
only the first line of each error in the one warning they give. Node's
|
|
123
|
+
`Cannot find module` error carries a multi-line `Require stack:`, and joined
|
|
124
|
+
whole into the `; `-separated message it made one warning dozens of lines
|
|
125
|
+
long; it now reads `could not resolve @react-pdf/font: Error: Cannot find
|
|
126
|
+
module '@react-pdf/font'; could not resolve pdfkit's fonts for …`.
|
|
127
|
+
|
|
128
|
+
## 0.1.1
|
|
129
|
+
|
|
130
|
+
### Patch Changes
|
|
131
|
+
|
|
132
|
+
- [#399](https://github.com/softistx/nxgt-material/pull/399) [`1abb908`](https://github.com/softistx/nxgt-material/commit/1abb90800ec213d8ec98abd7df5dda9f65c14204) Thanks [@SteveGT96](https://github.com/SteveGT96)! - The package manifest no longer carries a `repository` field. The source
|
|
133
|
+
repository is private, so the link npm showed for it led to a 404; the
|
|
134
|
+
README and the `docs/` shipped in the tarball remain the public reference.
|
|
135
|
+
|
|
136
|
+
- [#398](https://github.com/softistx/nxgt-material/pull/398) [`b4e5770`](https://github.com/softistx/nxgt-material/commit/b4e5770922ad4582a1ad2dcca439f7c8c999a0c7) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Docs: the roadmap's Shipped list now has 0.1.0 — the first release, holding the framework-free code `@nxgt/material` and `@nxgt/material-vue` share.
|
|
137
|
+
|
|
138
|
+
## 0.1.0
|
|
139
|
+
|
|
140
|
+
### Minor Changes
|
|
141
|
+
|
|
142
|
+
- [#391](https://github.com/softistx/nxgt-material/pull/391) [`deaf0c4`](https://github.com/softistx/nxgt-material/commit/deaf0c49cbc2268fd20e9e2272104dbd27e4ce7f) Thanks [@SteveGT96](https://github.com/SteveGT96)! - First release of `@nxgt/material-core`: the framework-free core that
|
|
143
|
+
`@nxgt/material` (React) and `@nxgt/material-vue` (Vue) share, as one copy.
|
|
144
|
+
The PDF document model (`/pdf/model`) and its react-pdf renderer
|
|
145
|
+
(`/pdf/render`, both also from `/pdf`), the print formatters (`/print-format`, `/print-value`,
|
|
146
|
+
`/print-table`, `/print-fraction-digits`), the PDF file helpers
|
|
147
|
+
(`/pdf-source`, `/pdf-file-name`, `/pdf-download`), serving a PDF
|
|
148
|
+
(`/pdf/http`, `/pdf/file-loader`), the PDF viewer's framework-free modules
|
|
149
|
+
(`/pdf-viewer`: page geometry, page sizes, scroll spy, text search), the
|
|
150
|
+
currency field's decimals (`/currency-digits`), the fields' blur layers
|
|
151
|
+
(`/field-blur-layers`) and the pdfkit fonts plugin (`/vite`).
|
|
152
|
+
`react` and `@react-pdf/renderer` are optional peers, needed only to render;
|
|
153
|
+
`vite` (6, 7 or 8) is one too, for the types of `/vite`.
|
|
154
|
+
Most apps get it through `@nxgt/material` or `@nxgt/material-vue`; a server
|
|
155
|
+
bundle that inlines either library (`ssr.noExternal`) must list
|
|
156
|
+
`@nxgt/material-core` beside it.
|
package/README.md
CHANGED
|
@@ -70,6 +70,7 @@ built-in.
|
|
|
70
70
|
| `/pdf-viewer` | The PDF viewer's pure half: page geometry and fit (`readerFitScale`, `placeholderSize`, `rotatedSize`, `PdfPageSize`, `FitMode`), page sizes (`readPageSizes`, `createPageSizesLoader`), the scroll spy (`createScrollSpy`, `revealHit`, `scrollIntoArea`), the opening page's pin (`pinToPage`, whose optional `onRelease` runs once when it lets go, and `pinHolds`, whether the view is still where it puts the page), text search (`pageTextFromItems`, `findTextMatches`, `searchDocument`), `escapeHtml`, `mapPdfOutline` |
|
|
71
71
|
| `/currency-digits` | `currencyFractionDigits` — the decimals `CurrencyField` shows |
|
|
72
72
|
| `/field-blur-layers` | `layerOf`, `openerOf`, `FieldLayers` — whose overlay a layer of the page is, for a field's blur |
|
|
73
|
+
| `/row-activation` | `isRowActivation`, `followRowLink`, `ROW_CONTROL_SELECTOR`, `ROW_LINK_SELECTOR`, `RowClick` — whether a click on a table row follows its link, and following it |
|
|
73
74
|
| `/format-file-size` | `formatFileSize` — a byte count as `'1.5 KB'` |
|
|
74
75
|
| `/slider-ticks` | `tickValues` — where a slider's tick marks sit |
|
|
75
76
|
| `/date-range` | `DATE_RANGE_PRESET_IDS`, `presetRange`, `resolvePresetRange`, `isSameDayRange`, `isRangeDisabled`, `withTimeOf`, `endOfDayTime`, `clampRangeEnd`, `keepRangeTimes` and the types `DayRange`, `PartialDayRange`, `DateRangePreset`, `DateRangePresetId`, `DateRangePresetOption`, `DateRangeRules` — `DateRangeField`'s presets and times |
|
|
@@ -465,6 +466,24 @@ field.addEventListener('focusout', (event) => {
|
|
|
465
466
|
});
|
|
466
467
|
```
|
|
467
468
|
|
|
469
|
+
### A clickable table row: `/row-activation`
|
|
470
|
+
|
|
471
|
+
A row whose first cell links to its page should follow that link on a click
|
|
472
|
+
anywhere else on the row — but not on its checkbox or its buttons, not from
|
|
473
|
+
a menu its cell opened into `<body>`, and not when the click ends a text
|
|
474
|
+
selection. `isRowActivation` says whether a click is one; `followRowLink`
|
|
475
|
+
clicks the row's link (`ROW_LINK_SELECTOR`) with the click's modifier keys,
|
|
476
|
+
so a router's link navigates as it does on its own click. Both read the DOM
|
|
477
|
+
when called, never at import.
|
|
478
|
+
|
|
479
|
+
```ts
|
|
480
|
+
import { followRowLink, isRowActivation } from '@nxgt/material-core/row-activation';
|
|
481
|
+
|
|
482
|
+
row.addEventListener('click', (event) => {
|
|
483
|
+
if (isRowActivation(event, row)) followRowLink(row, event);
|
|
484
|
+
});
|
|
485
|
+
```
|
|
486
|
+
|
|
468
487
|
### Bundling pdfkit's fonts: `/vite`
|
|
469
488
|
|
|
470
489
|
An SSR server bundled into a single file with no `node_modules` needs
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** What a click inside a row must not activate the row from: its controls
|
|
2
|
+
* (checkboxes, buttons, links, menus, fields) and anything marked
|
|
3
|
+
* `data-row-click-ignore`. */
|
|
4
|
+
export declare const ROW_CONTROL_SELECTOR: string;
|
|
5
|
+
/** The row's own link, which a click on the row follows: the element marked
|
|
6
|
+
* `data-slot="data-table-row-link"`, else the first link of the cell marked
|
|
7
|
+
* `data-row-link-cell` (for a link component that drops the `data-slot` it
|
|
8
|
+
* is given). */
|
|
9
|
+
export declare const ROW_LINK_SELECTOR = "[data-slot=\"data-table-row-link\"],[data-row-link-cell] a[href]";
|
|
10
|
+
/** The parts of a click this module reads. */
|
|
11
|
+
export type RowClick = {
|
|
12
|
+
target: EventTarget | null;
|
|
13
|
+
button: number;
|
|
14
|
+
defaultPrevented: boolean;
|
|
15
|
+
ctrlKey?: boolean;
|
|
16
|
+
metaKey?: boolean;
|
|
17
|
+
shiftKey?: boolean;
|
|
18
|
+
altKey?: boolean;
|
|
19
|
+
};
|
|
20
|
+
/** Whether `event`, a click that reached `row`, activates the row: a primary
|
|
21
|
+
* click, not handled yet, inside the row's own DOM (not in a portal its
|
|
22
|
+
* cells opened), not on one of its controls, and not the end of a text
|
|
23
|
+
* selection in it. */
|
|
24
|
+
export declare function isRowActivation(event: RowClick, row: Element): boolean;
|
|
25
|
+
/** Follows the row's link (`ROW_LINK_SELECTOR`) as if it had been clicked,
|
|
26
|
+
* with the modifier keys of `event`: a router's link navigates as it does on
|
|
27
|
+
* its own click, Ctrl/Cmd+click opens a tab where the browser allows it.
|
|
28
|
+
* `false` when the row has no link. */
|
|
29
|
+
export declare function followRowLink(row: Element, event: RowClick): boolean;
|
|
30
|
+
//# sourceMappingURL=row-activation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"row-activation.d.ts","sourceRoot":"","sources":["../../src/lib/row-activation.ts"],"names":[],"mappings":"AAIA;;8BAE8B;AAC9B,eAAO,MAAM,oBAAoB,QAgBtB,CAAC;AAEZ;;;gBAGgB;AAChB,eAAO,MAAM,iBAAiB,qEACmC,CAAC;AAElE,8CAA8C;AAC9C,MAAM,MAAM,QAAQ,GAAG;IACtB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAMF;;;sBAGsB;AACtB,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAgBtE;AAED;;;uCAGuC;AACvC,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAgBpE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/lib/row-activation.ts
|
|
2
|
+
var ROW_CONTROL_SELECTOR = [
|
|
3
|
+
"a[href]",
|
|
4
|
+
"button",
|
|
5
|
+
"input",
|
|
6
|
+
"select",
|
|
7
|
+
"textarea",
|
|
8
|
+
"label",
|
|
9
|
+
"summary",
|
|
10
|
+
'[contenteditable="true"]',
|
|
11
|
+
'[role="button"]',
|
|
12
|
+
'[role="checkbox"]',
|
|
13
|
+
'[role="link"]',
|
|
14
|
+
'[role="menuitem"]',
|
|
15
|
+
'[role="switch"]',
|
|
16
|
+
'[role="combobox"]',
|
|
17
|
+
"[data-row-click-ignore]"
|
|
18
|
+
].join(",");
|
|
19
|
+
var ROW_LINK_SELECTOR = '[data-slot="data-table-row-link"],[data-row-link-cell] a[href]';
|
|
20
|
+
function isElement(target) {
|
|
21
|
+
return target !== null && typeof target.closest === "function";
|
|
22
|
+
}
|
|
23
|
+
function isRowActivation(event, row) {
|
|
24
|
+
if (event.defaultPrevented || event.button !== 0)
|
|
25
|
+
return false;
|
|
26
|
+
const { target } = event;
|
|
27
|
+
if (!isElement(target) || !row.contains(target))
|
|
28
|
+
return false;
|
|
29
|
+
const control = target.closest(ROW_CONTROL_SELECTOR);
|
|
30
|
+
if (control && control !== row && row.contains(control))
|
|
31
|
+
return false;
|
|
32
|
+
const selection = row.ownerDocument?.getSelection?.();
|
|
33
|
+
if (selection && !selection.isCollapsed && selection.anchorNode && row.contains(selection.anchorNode)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
function followRowLink(row, event) {
|
|
39
|
+
const link = row.querySelector(ROW_LINK_SELECTOR);
|
|
40
|
+
const view = row.ownerDocument?.defaultView;
|
|
41
|
+
if (!link || !view)
|
|
42
|
+
return false;
|
|
43
|
+
link.dispatchEvent(new view.MouseEvent("click", {
|
|
44
|
+
bubbles: true,
|
|
45
|
+
cancelable: true,
|
|
46
|
+
button: 0,
|
|
47
|
+
ctrlKey: event.ctrlKey,
|
|
48
|
+
metaKey: event.metaKey,
|
|
49
|
+
shiftKey: event.shiftKey,
|
|
50
|
+
altKey: event.altKey
|
|
51
|
+
}));
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
ROW_CONTROL_SELECTOR,
|
|
56
|
+
ROW_LINK_SELECTOR,
|
|
57
|
+
followRowLink,
|
|
58
|
+
isRowActivation
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
//# debugId=B5C72BCA21047D6B64756E2164756E21
|
|
62
|
+
//# sourceMappingURL=row-activation.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/lib/row-activation.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"// A clickable table row: a click anywhere on the row, but on a control of its\n// own, does what the row's link (or its click handler) does. Shared by both\n// libraries' `DataTable`. Reads the DOM only when called, never at import.\n\n/** What a click inside a row must not activate the row from: its controls\n * (checkboxes, buttons, links, menus, fields) and anything marked\n * `data-row-click-ignore`. */\nexport const ROW_CONTROL_SELECTOR = [\n\t'a[href]',\n\t'button',\n\t'input',\n\t'select',\n\t'textarea',\n\t'label',\n\t'summary',\n\t'[contenteditable=\"true\"]',\n\t'[role=\"button\"]',\n\t'[role=\"checkbox\"]',\n\t'[role=\"link\"]',\n\t'[role=\"menuitem\"]',\n\t'[role=\"switch\"]',\n\t'[role=\"combobox\"]',\n\t'[data-row-click-ignore]',\n].join(',');\n\n/** The row's own link, which a click on the row follows: the element marked\n * `data-slot=\"data-table-row-link\"`, else the first link of the cell marked\n * `data-row-link-cell` (for a link component that drops the `data-slot` it\n * is given). */\nexport const ROW_LINK_SELECTOR =\n\t'[data-slot=\"data-table-row-link\"],[data-row-link-cell] a[href]';\n\n/** The parts of a click this module reads. */\nexport type RowClick = {\n\ttarget: EventTarget | null;\n\tbutton: number;\n\tdefaultPrevented: boolean;\n\tctrlKey?: boolean;\n\tmetaKey?: boolean;\n\tshiftKey?: boolean;\n\taltKey?: boolean;\n};\n\nfunction isElement(target: EventTarget | null): target is Element {\n\treturn target !== null && typeof (target as Element).closest === 'function';\n}\n\n/** Whether `event`, a click that reached `row`, activates the row: a primary\n * click, not handled yet, inside the row's own DOM (not in a portal its\n * cells opened), not on one of its controls, and not the end of a text\n * selection in it. */\nexport function isRowActivation(event: RowClick, row: Element): boolean {\n\tif (event.defaultPrevented || event.button !== 0) return false;\n\tconst { target } = event;\n\tif (!isElement(target) || !row.contains(target)) return false;\n\tconst control = target.closest(ROW_CONTROL_SELECTOR);\n\tif (control && control !== row && row.contains(control)) return false;\n\tconst selection = row.ownerDocument?.getSelection?.();\n\tif (\n\t\tselection &&\n\t\t!selection.isCollapsed &&\n\t\tselection.anchorNode &&\n\t\trow.contains(selection.anchorNode)\n\t) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/** Follows the row's link (`ROW_LINK_SELECTOR`) as if it had been clicked,\n * with the modifier keys of `event`: a router's link navigates as it does on\n * its own click, Ctrl/Cmd+click opens a tab where the browser allows it.\n * `false` when the row has no link. */\nexport function followRowLink(row: Element, event: RowClick): boolean {\n\tconst link = row.querySelector(ROW_LINK_SELECTOR);\n\tconst view = row.ownerDocument?.defaultView;\n\tif (!link || !view) return false;\n\tlink.dispatchEvent(\n\t\tnew view.MouseEvent('click', {\n\t\t\tbubbles: true,\n\t\t\tcancelable: true,\n\t\t\tbutton: 0,\n\t\t\tctrlKey: event.ctrlKey,\n\t\t\tmetaKey: event.metaKey,\n\t\t\tshiftKey: event.shiftKey,\n\t\t\taltKey: event.altKey,\n\t\t}),\n\t);\n\treturn true;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";AAOO,IAAM,uBAAuB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,EAAE,KAAK,GAAG;AAMH,IAAM,oBACZ;AAaD,SAAS,SAAS,CAAC,QAA+C;AAAA,EACjE,OAAO,WAAW,QAAQ,OAAQ,OAAmB,YAAY;AAAA;AAO3D,SAAS,eAAe,CAAC,OAAiB,KAAuB;AAAA,EACvE,IAAI,MAAM,oBAAoB,MAAM,WAAW;AAAA,IAAG,OAAO;AAAA,EACzD,QAAQ,WAAW;AAAA,EACnB,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,IAAI,SAAS,MAAM;AAAA,IAAG,OAAO;AAAA,EACxD,MAAM,UAAU,OAAO,QAAQ,oBAAoB;AAAA,EACnD,IAAI,WAAW,YAAY,OAAO,IAAI,SAAS,OAAO;AAAA,IAAG,OAAO;AAAA,EAChE,MAAM,YAAY,IAAI,eAAe,eAAe;AAAA,EACpD,IACC,aACA,CAAC,UAAU,eACX,UAAU,cACV,IAAI,SAAS,UAAU,UAAU,GAChC;AAAA,IACD,OAAO;AAAA,EACR;AAAA,EACA,OAAO;AAAA;AAOD,SAAS,aAAa,CAAC,KAAc,OAA0B;AAAA,EACrE,MAAM,OAAO,IAAI,cAAc,iBAAiB;AAAA,EAChD,MAAM,OAAO,IAAI,eAAe;AAAA,EAChC,IAAI,CAAC,QAAQ,CAAC;AAAA,IAAM,OAAO;AAAA,EAC3B,KAAK,cACJ,IAAI,KAAK,WAAW,SAAS;AAAA,IAC5B,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,IACf,UAAU,MAAM;AAAA,IAChB,QAAQ,MAAM;AAAA,EACf,CAAC,CACF;AAAA,EACA,OAAO;AAAA;",
|
|
8
|
+
"debugId": "B5C72BCA21047D6B64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
package/docs/roadmap.md
CHANGED
|
@@ -31,6 +31,10 @@ Nothing in progress right now; see Next.
|
|
|
31
31
|
|
|
32
32
|
## Shipped
|
|
33
33
|
|
|
34
|
+
- **Clickable table rows** (`/row-activation`) — whether a click on a row
|
|
35
|
+
should follow its link (not on a control, not in a portal, not the end of
|
|
36
|
+
a text selection) and following it with the click's modifier keys, for
|
|
37
|
+
both libraries' `DataTable`. 0.4.0.
|
|
34
38
|
- **Date range presets and times** (`/date-range`) — the built-in presets'
|
|
35
39
|
ranges, whether a field's rules rule a range out, and the time of day on
|
|
36
40
|
each end, for both libraries' `DateRangeField`. 0.3.0.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/material-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
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 file-size formatter, the field-blur layers, the date range presets, the file preview's kind detection and text reader, the pdfkit fonts Vite plugin and the Node-only pdfkit fonts resolution for Next.js and Nuxt builds",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": {
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"dist",
|
|
14
14
|
"docs",
|
|
15
15
|
"README.md",
|
|
16
|
+
"CHANGELOG.md",
|
|
16
17
|
"package.json",
|
|
17
18
|
"LICENSE"
|
|
18
19
|
],
|
|
@@ -92,6 +93,11 @@
|
|
|
92
93
|
"import": "./dist/lib/field-blur-layers.js",
|
|
93
94
|
"default": "./dist/lib/field-blur-layers.js"
|
|
94
95
|
},
|
|
96
|
+
"./row-activation": {
|
|
97
|
+
"types": "./dist/lib/row-activation.d.ts",
|
|
98
|
+
"import": "./dist/lib/row-activation.js",
|
|
99
|
+
"default": "./dist/lib/row-activation.js"
|
|
100
|
+
},
|
|
95
101
|
"./format-file-size": {
|
|
96
102
|
"types": "./dist/lib/format-file-size.d.ts",
|
|
97
103
|
"import": "./dist/lib/format-file-size.js",
|
|
@@ -171,6 +177,7 @@
|
|
|
171
177
|
"src/lib/pdf-download.ts",
|
|
172
178
|
"src/lib/currency-digits.ts",
|
|
173
179
|
"src/lib/field-blur-layers.ts",
|
|
180
|
+
"src/lib/row-activation.ts",
|
|
174
181
|
"src/lib/format-file-size.ts",
|
|
175
182
|
"src/lib/slider-ticks.ts",
|
|
176
183
|
"src/lib/date-range.ts",
|