@deviceinsight/ng-ui-components 7.21.0 → 7.22.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/README.md CHANGED
@@ -1,99 +1,173 @@
1
- # Linking for local development
2
-
3
- We recommend using `yalc` tool for linking `ng-ui-components`. It's because `yalc` generates exactly the same package as
4
- it would be published to the npm registry, especially it removes files that should be ignored and their existence cause
5
- problems when we use `yarn link`.
1
+ # General
6
2
 
7
- Here's how to do the linking:
3
+ This project contains the higher-level React components shared by
4
+ [NG-UI](https://gitlab.device-insight.com/ng-ui/ng-ui) and custom projects.
5
+ It is published as `@deviceinsight/ng-ui-components` and builds on
6
+ `@deviceinsight/ng-ui-basic-components` and `@deviceinsight/ng-ui-api-client`.
8
7
 
9
- ```shell
10
- yarn link-local
8
+ The package is ESM-first (`dist/index.js`) with a CommonJS build (`dist/index.cjs`)
9
+ and type declarations (`dist/types/index.d.ts`). The bundled stylesheet is exported
10
+ separately and has to be imported by the consuming project:
11
11
 
12
- # in the project where you want to link this library to:
13
- yalc link "@deviceinsight/ng-ui-components"
12
+ ```ts
13
+ import '@deviceinsight/ng-ui-components/style.css';
14
14
  ```
15
15
 
16
- # Releasing the library using git flow
17
-
18
- ## Prerequisites
19
-
20
- ### git flow
21
-
22
- The git flow tools need to be installed. This depends on your operating system.
16
+ `react`, `react-dom`, `i18next`, `react-i18next` and `react-router-dom` are peer
17
+ dependencies and have to be provided by the consuming project.
23
18
 
24
- They can be also installed from the git repo: https://github.com/petervanderdoes/gitflow-avh
19
+ ## Contents
25
20
 
26
- After git flow is installed, the repo needs to be initialized. Run `git flow init` and answer every
27
- question with the default (press Enter/Return).
21
+ `src/index.ts` is the public API. It currently exports:
28
22
 
29
- ## Building a release
23
+ - **Inputs** — `DateInput`, `DateTimeInput`, `UrnInput`, `ValidatedTextInput`,
24
+ `SelectWithSearch`, `SelectWithSearchAsync`, `PeriodPicker`, `Slider`
25
+ - **Data display** — `Reactable`, `ReactableWithClientSidePagination`, `Pagination`,
26
+ `TreeView` (plus `getTreeNodePathById`), `Chart`, `InfoBox`, `ContentHeader`
27
+ - **Color pickers** — `ColorPicker` / `GridColorPicker`, `GradientColorPicker`
28
+ - **Navigation** — `RouteLink`, `RouteTabs`, `MultiMenu`, `MultiMenuItem`
29
+ - **Upload** — `FileUpload`, `ImageUpload`
30
+ - **SVG** — `SvgImage` and the helpers `getSvgElement`, `getMutableNodeList`,
31
+ `validateSvg`
32
+ - **Prompt** — `withPrompt`
33
+ - **Message box** — `messageBoxSuccess`, `messageBoxInfo`, `messageBoxWarn`,
34
+ `messageBoxError`, `messageBoxDismissSingle`, `messageBoxDismissGroup`,
35
+ `messageBoxDismissAll`, `setGlobalMessageBoxOptions`,
36
+ `setGlobalErrorMessageBoxOptions`, `MessageBoxContainer`
37
+ - **Utilities** — `uuidV4`, `nanoid10`, `initializeTranslation`
38
+ - the accompanying types (`ReactableProps`, `ReactableColumnDef`, `Period`,
39
+ `SvgImageProps`, `PaginationSettings`, …)
30
40
 
31
- To build a release of this library, execute `./release.sh`, which consists of the following steps:
41
+ Translations live in `src/i18n` and are set up by calling `initializeTranslation`.
42
+ `src/modules` holds non-component code (message box, utils), `src/styles` the
43
+ stylesheet, `src/utils` shared helpers.
32
44
 
33
- ### Before the release: Check for vulnerabilities and run the tests
45
+ # Development
34
46
 
35
- Vulnerabilities can occur at any time.
36
- To be sure, the pipeline for the branches and the tags created
37
- in the release process will not fail, it is wise to run the checks locally before building the
38
- release.
39
- To do this, run:
47
+ Node is pinned via `.nvmrc` (see also the `engines` field in `package.json`).
40
48
 
41
- ```
49
+ ```shell
42
50
  npm install
43
- npm run scan
44
- npm run test
51
+ npm run storybook # dev server on http://localhost:6006
45
52
  ```
46
53
 
47
- ### Building the release
48
-
49
- 1. Switch to develop branch and make sure both main and develop are current:
54
+ Available scripts:
50
55
 
51
- `git checkout develop && git pull && git fetch origin main:main`
56
+ | Script | Description |
57
+ | ------------------------- | -------------------------------------------------------------------------- |
58
+ | `npm run build` | Cleans `dist`, bundles with Vite and emits types via `tsconfig.types.json` |
59
+ | `npm test` | Runs the Vitest suite (watch mode by default, `--run` for a single pass) |
60
+ | `npm run watch` | Rebuilds and runs `yalc push` on every successful compile |
61
+ | `npm run clean` | Removes `dist` |
62
+ | `npm run storybook` | Starts Storybook on port 6006 |
63
+ | `npm run build-storybook` | Builds the static Storybook |
64
+ | `npm run typecheck` | `tsc --noEmit` |
65
+ | `npm run lint` | Lints with oxlint and checks formatting with Prettier |
66
+ | `npm run prettier` | Formats the sources and `.mdx` files |
67
+ | `npm run scan` | Vulnerability scan via `audit-ci` using `scan-config.json5` |
52
68
 
53
- 2. Get the upcoming release from `package.json` and start the release:
69
+ Tests use Vitest with `happy-dom` and Testing Library; the setup lives in
70
+ `vitest.setup.tsx` and the config in `vitest.config.mts`. Components are additionally
71
+ exercised via Storybook stories (`*.stories.tsx`).
54
72
 
55
- `git flow release start $RELEASE_VERSION`, e.g. `git flow release start 1.2.0`.
73
+ Commits are checked by a husky `pre-commit` hook that runs `lint-staged`
74
+ (prettier on the staged files).
56
75
 
57
- 3. Edit the version in `package.json`.
76
+ `CHANGELOG.md` is maintained per version. Renovate dependency updates append their
77
+ entry automatically via the `postUpgradeTasks` hook in `renovate.json`, which calls
78
+ `./update-changelog.sh <depName> <currentVersion> <newVersion>`.
58
79
 
59
- 3.1. Edit the version in `package.json`, remove the `-SNAPSHOT`.
80
+ # Linking for local development
60
81
 
61
- 3.2. Commit `package.json`. Commit message should be `Release $RELEASE_VERSION`, e.g. `Release 1.2.0`.
82
+ We recommend using the `yalc` tool for linking `@deviceinsight/ng-ui-components`. It's because `yalc` generates exactly the same package as
83
+ it would be published to the npm registry, especially it removes files that should be ignored and their existence cause
84
+ problems when we use `npm link`.
62
85
 
63
- 4. Finish the release:
86
+ Here's how to do the linking:
64
87
 
65
- `git flow release finish`
88
+ ```shell
89
+ npm run build
90
+ npx yalc publish
66
91
 
67
- This will merge the release branch into the `main` branch and create a tag.
68
- It will also merge the release branch into the `develop` branch.
92
+ # in the project where you want to link this library to:
93
+ npx yalc link "@deviceinsight/ng-ui-components"
94
+ ```
69
95
 
70
- After this you should be on the `develop` branch.
96
+ # CI
71
97
 
72
- 4.1 A merge conflict might occur in `package.json` for the `version`, when main is merged into the develop branch:
98
+ `.gitlab-ci.yml` installs the dependencies and then runs `test`, `lint` and `typecheck`
99
+ on every branch except `main`. The `audit` job (`npm run scan`) only runs on `develop`,
100
+ `feature/*` and `renovate/*` branches, so hotfixes and tags are not blocked by it. On `develop` the
101
+ `pages` job publishes the static Storybook to GitLab Pages. The `publish` job runs for `develop` and for tags:
102
+ `-SNAPSHOT` versions are published to the internal Nexus registry under the `next`
103
+ tag, releases go to the public npm registry. A release older than the currently
104
+ published `latest` is published under a `hotfix-<major>.<minor>` tag so that `latest`
105
+ is not moved backwards. `publish_alpha` is a manual job that publishes an alpha
106
+ prerelease of the `VERSION` variable to the internal registry under `next`.
73
107
 
74
- Resolve it by taking the version of the `develop` branch. Then run `npm install` to resolve conflicts in `package-lock.version`.
108
+ # Releasing the library using git flow
75
109
 
76
- Run `git status` to see if there are more conflicts. If there are, resolve them and `git add` the fixed files.
110
+ ## Prerequisites
77
111
 
78
- If there are no more conflicts, run `git add package*` and `git commit`.
112
+ ### git flow
79
113
 
80
- 5. Start a new snapshot version:
114
+ The git flow tools need to be installed. This depends on your operating system.
81
115
 
82
- 5.1.
83
- Edit the version in `package.json`,
84
- increment the minor version (e.g., from `1.1.0` to `1.2.0`) and add the `-SNAPSHOT` again,
85
- so that the version is e.g. `1.2.0-SNAPSHOT`.
116
+ They can be also installed from the git repo: https://github.com/petervanderdoes/gitflow-avh
86
117
 
87
- 5.2. Run `npm install`.
118
+ After git flow is installed, the repo needs to be initialized. Run `git flow init` and answer every
119
+ question with the default (press Enter/Return). The script verifies that the branches
120
+ are named `main` and `develop`.
88
121
 
89
- 5.2. Commit `package.json` and `package-lock.json`. Commit message should be `Starting $NEW_SNAPSHOT_VERSION`, e.g. `Starting 1.2.0`.
122
+ ## Releasing the develop branch
90
123
 
91
- 6. Push the branches and the tag:
124
+ Run the release script from the repository root:
92
125
 
93
- On branch `develop`:
126
+ ```shell
127
+ ./release.sh
128
+ ```
94
129
 
95
- `git push`
96
- `git checkout main`
97
- `git push`
98
- `git push --tags`
99
- `git checkout develop`
130
+ Before running it, make sure the workarea is clean and all commits on `develop` are pushed; otherwise the script aborts.
131
+ It releases the current version from `package.json` (without `-SNAPSHOT`) and afterwards starts the next minor snapshot version.
132
+
133
+ ## Building a hotfix for a specific version of this library
134
+
135
+ When building a hotfix in `ng-ui-scale`, first check which version of this library is used on the `main` branch of `ng-ui-scale`, e.g. with `git show origin/main:package.json | grep ng-ui-components`.
136
+ Then build the hotfix on top of exactly that version, so that no unrelated changes from newer releases end up in the `ng-ui-scale` hotfix.
137
+ Do not use `release.sh` or `git flow hotfix` for this: `git flow hotfix finish` merges into `main`, which already contains the newer release.
138
+
139
+ Example: `ng-ui-scale` uses 7.22.0 while 7.24.0 is already released (the version on `main` of this library):
140
+
141
+ 1. Create the branch `hotfix/7.22.1` from the tag 7.22.0:
142
+ ```shell
143
+ git fetch --tags
144
+ git checkout -b hotfix/7.22.1 7.22.0
145
+ ```
146
+ 2. Set the version in `package.json` and `package-lock.json` to 7.22.1:
147
+ ```shell
148
+ npm version 7.22.1 --no-git-tag-version
149
+ ```
150
+ If the `audit` job in `.gitlab-ci.yml` still runs on every branch except `main`, copy its `rules` from `develop`, so that the vulnerability audit does not block the hotfix pipeline.
151
+ 3. Implement or cherry-pick the changes needed for the hotfix, either directly on the hotfix branch or in a feature branch that is merged into it.
152
+ 4. Add a `## Version 7.22.1` entry to `CHANGELOG.md` describing the changes in the hotfix.
153
+ 5. Run `npm run build`, `npm test -- --run` and `npm run lint` to verify there are no errors.
154
+ 6. Commit the changes.
155
+ 7. Tag the hotfix commit and push the tag:
156
+ ```shell
157
+ git tag -a 7.22.1 -m "Hotfix 7.22.1"
158
+ git push origin 7.22.1
159
+ ```
160
+ The `publish` CI job builds the tag and publishes it to npm.
161
+ Because 7.22.1 is older than the `latest` version, it is published under the dist-tag `hotfix-7.22` and `latest` stays at 7.24.0.
162
+ 8. Merge the hotfix branch into `develop` and push `develop`:
163
+ ```shell
164
+ git checkout develop
165
+ git pull
166
+ git merge --no-ff hotfix/7.22.1
167
+ git push
168
+ ```
169
+ `package.json` and `package-lock.json` will conflict; keep the `-SNAPSHOT` version of `develop` and run `npm install` before committing the merge.
170
+ In `CHANGELOG.md`, keep the 7.22.1 entry between the entries for 7.23.0 and 7.22.0.
171
+ Do not merge the hotfix branch into `main`.
172
+ 9. Delete the local hotfix branch: `git branch -d hotfix/7.22.1`.
173
+ 10. Update `ng-ui-scale` on its hotfix branch to 7.22.1.
package/dist/index.cjs CHANGED
@@ -6,7 +6,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
9
  var __copyProps = (to, from, except, desc) => {
11
10
  if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
11
  key = keys[i];
@@ -73,7 +72,6 @@ let _svgdotjs_svg_js = require("@svgdotjs/svg.js");
73
72
  let highcharts = require("highcharts");
74
73
  highcharts = __toESM(highcharts, 1);
75
74
  let highcharts_react_official = require("highcharts-react-official");
76
- highcharts_react_official = __toESM(highcharts_react_official, 1);
77
75
  let _rc_component_slider = require("@rc-component/slider");
78
76
  _rc_component_slider = __toESM(_rc_component_slider, 1);
79
77
  let _rc_component_tooltip = require("@rc-component/tooltip");
@@ -3326,9 +3324,10 @@ var getClickConfiguration = (onClick) => {
3326
3324
  var Chart = class extends react.Component {
3327
3325
  constructor(..._args) {
3328
3326
  super(..._args);
3329
- this.state = {};
3327
+ this.state = { titleApplied: false };
3330
3328
  this.chart = null;
3331
3329
  this.ro = null;
3330
+ this.titleTimeoutId = void 0;
3332
3331
  this.handleChart = (chart) => {
3333
3332
  this.chart = chart;
3334
3333
  this.ro = new ResizeObserver(() => {
@@ -3338,8 +3337,16 @@ var Chart = class extends react.Component {
3338
3337
  };
3339
3338
  }
3340
3339
  componentDidMount() {
3340
+ this.titleTimeoutId = setTimeout(() => this.setState({ titleApplied: true }), 0);
3341
+ }
3342
+ /**
3343
+ * Builds the Highcharts configuration from the props. Everything here is derived, so it is
3344
+ * rebuilt while rendering rather than mirrored into state.
3345
+ */
3346
+ buildOptions() {
3341
3347
  const { type, title, items, tooltipTitle, valueFormatter, onClick } = this.props;
3342
- this.setState({
3348
+ const { titleApplied } = this.state;
3349
+ return {
3343
3350
  ...initialOptions,
3344
3351
  plotOptions: {
3345
3352
  ...initialOptions.plotOptions,
@@ -3356,44 +3363,12 @@ var Chart = class extends react.Component {
3356
3363
  ...initialOptions.legend,
3357
3364
  enabled: type === "pie"
3358
3365
  },
3359
- yAxis: {
3360
- ...initialOptions.yAxis,
3361
- enabled: type === "column",
3362
- title: { text: title || "" }
3363
- },
3364
- series: [{
3365
- type,
3366
- innerSize: "50%",
3367
- data: items.map(({ label, value }) => [label, value])
3368
- }]
3369
- });
3370
- setTimeout(() => {
3371
- this.setState({ title: {
3372
- ...initialOptions.title,
3373
- text: type === "column" ? "" : title || ""
3374
- } });
3375
- }, 0);
3376
- }
3377
- componentDidUpdate(prevProps) {
3378
- const { type, title, items, tooltipTitle, valueFormatter, onClick } = this.props;
3379
- if (title !== prevProps.title) this.setState({
3380
3366
  title: {
3381
- ...this.state.title,
3382
- text: type === "column" ? "" : title || ""
3383
- },
3384
- yAxis: {
3385
- ...this.state.yAxis,
3386
- title: { text: title || "" }
3387
- }
3388
- });
3389
- if (type !== prevProps.type) this.setState({
3390
- legend: {
3391
- ...this.state.legend,
3392
- enabled: type === "pie"
3367
+ ...initialOptions.title,
3368
+ text: titleApplied && type !== "column" ? title || "" : ""
3393
3369
  },
3394
- title: { text: type === "column" ? "" : title || "" },
3395
3370
  yAxis: {
3396
- ...this.state.yAxis,
3371
+ ...initialOptions.yAxis,
3397
3372
  enabled: type === "column",
3398
3373
  title: { text: type === "column" ? title || "" : "" }
3399
3374
  },
@@ -3402,35 +3377,19 @@ var Chart = class extends react.Component {
3402
3377
  innerSize: "50%",
3403
3378
  data: items.map(({ label, value }) => [label, value])
3404
3379
  }]
3405
- });
3406
- if (!(0, lodash.isEqual)(items, prevProps.items)) this.setState({ series: [{
3407
- type,
3408
- innerSize: "50%",
3409
- data: items.map(({ label, value }) => [label, value])
3410
- }] });
3411
- if (tooltipTitle !== prevProps.tooltipTitle || valueFormatter !== prevProps.valueFormatter || onClick !== prevProps.onClick) this.setState({
3412
- tooltip: {
3413
- ...initialOptions.tooltip,
3414
- formatter() {
3415
- const format = valueFormatter || ((value) => value);
3416
- return createTooltip(tooltipTitle || "", this.point.name, format(this.point.y));
3417
- }
3418
- },
3419
- plotOptions: {
3420
- ...initialOptions.plotOptions,
3421
- ...getClickConfiguration(onClick)
3422
- }
3423
- });
3380
+ };
3424
3381
  }
3425
3382
  componentWillUnmount() {
3383
+ clearTimeout(this.titleTimeoutId);
3426
3384
  if (this.ro && this.chart?.renderTo) this.ro.unobserve(this.chart.renderTo);
3427
3385
  this.chart = null;
3428
3386
  this.ro = null;
3429
3387
  }
3430
3388
  render() {
3431
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(highcharts_react_official.default, {
3389
+ const built = this.buildOptions();
3390
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(highcharts_react_official.HighchartsReact, {
3432
3391
  highcharts: highcharts.default,
3433
- options: this.props.updateOptions ? this.props.updateOptions(this.state) : this.state,
3392
+ options: this.props.updateOptions ? this.props.updateOptions(built) : built,
3434
3393
  containerProps: { className: this.props.className },
3435
3394
  callback: this.handleChart
3436
3395
  });
@@ -3438,54 +3397,15 @@ var Chart = class extends react.Component {
3438
3397
  };
3439
3398
  //#endregion
3440
3399
  //#region src/components/slider/RcSliderWithTooltip.tsx
3441
- var import_raf = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports) => {
3442
- Object.defineProperty(exports, "__esModule", { value: true });
3443
- exports.default = void 0;
3444
- var raf = (callback) => +setTimeout(callback, 16);
3445
- var caf = (num) => clearTimeout(num);
3446
- if (typeof window !== "undefined" && "requestAnimationFrame" in window) {
3447
- raf = (callback) => window.requestAnimationFrame(callback);
3448
- caf = (handle) => window.cancelAnimationFrame(handle);
3449
- }
3450
- var rafUUID = 0;
3451
- var rafIds = /* @__PURE__ */ new Map();
3452
- function cleanup(id) {
3453
- rafIds.delete(id);
3454
- }
3455
- var wrapperRaf = (callback, times = 1) => {
3456
- rafUUID += 1;
3457
- const id = rafUUID;
3458
- function callRef(leftTimes) {
3459
- if (leftTimes === 0) {
3460
- cleanup(id);
3461
- callback();
3462
- } else {
3463
- const realId = raf(() => {
3464
- callRef(leftTimes - 1);
3465
- });
3466
- rafIds.set(id, realId);
3467
- }
3468
- }
3469
- callRef(times);
3470
- return id;
3471
- };
3472
- wrapperRaf.cancel = (id) => {
3473
- const realId = rafIds.get(id);
3474
- cleanup(id);
3475
- return caf(realId);
3476
- };
3477
- if (process.env.NODE_ENV !== "production") wrapperRaf.ids = () => rafIds;
3478
- exports.default = wrapperRaf;
3479
- })))(), 1);
3480
3400
  var HandleTooltip = (props) => {
3481
3401
  const { value, children, visible, tipFormatter = (val) => `${val}`, ...restProps } = props;
3482
3402
  const tooltipRef = (0, react.useRef)(null);
3483
3403
  const rafRef = (0, react.useRef)(null);
3484
3404
  function cancelKeepAlign() {
3485
- if (rafRef.current) import_raf.default.cancel(rafRef.current);
3405
+ if (rafRef.current) cancelAnimationFrame(rafRef.current);
3486
3406
  }
3487
3407
  function keepAlign() {
3488
- rafRef.current = (0, import_raf.default)(() => {
3408
+ rafRef.current = requestAnimationFrame(() => {
3489
3409
  tooltipRef.current?.forceAlign();
3490
3410
  });
3491
3411
  }